diff options
Diffstat (limited to 'Master/texmf-dist/source/latex')
43 files changed, 3569 insertions, 3082 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx index 179f45d11c8..5003992c6e0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx @@ -33,8 +33,7 @@ %% %% ----------------------------------------------------------------------- % -%<*driver|package> -\RequirePackage{l3names}[2012/07/15] +%<package>\RequirePackage{l3names}[2012/07/15] %<package>\@ifpackagelater{l3names}{2012/07/15} %<package> {} %<package> {% @@ -47,10 +46,11 @@ %<package> }% %<package> \endinput %<package> } +%<*driver|package> \def\ExplFileName{expl3} \def\ExplFileDescription{L3 Experimental code bundle wrapper} -\def\ExplFileDate{2012/07/16} -\def\ExplFileVersion{3990} +\def\ExplFileDate{2012/08/14} +\def\ExplFileVersion{4091} %</driver|package> %<*driver> \documentclass[full]{l3doc} @@ -1080,37 +1080,71 @@ { \token_to_str:N #1 } } } - \cs_set_protected:Npn \tl_set:Nn #1#2 - { - \__cs_check_exists:N #1 - \cs_set_nopar:Npx #1 { \exp_not:n {#2} } - } - \cs_set_protected:Npn \tl_set:Nx #1#2 +% \end{macrocode} +% No \cs{tl_map_\ldots} yet as the mechanisms are not fully in place. Thus +% instead do a more low level set up for a mapping, as in \pkg{l3basics}. +% \begin{macrocode} + \cs_set_protected:Npn \__cs_tmp:w #1 { - \__cs_check_exists:N #1 - \cs_set_nopar:Npx #1 {#2} + \if_meaning:w ? #1 + \exp_after:wN \use_none_delimit_by_q_recursion_stop:w + \fi: + \use:x + { + \cs_set_protected:Npn #1 \exp_not:n { ##1 ##2 } + { + \__cs_check_exists:N \exp_not:n {##1} + \exp_not:o { #1 {##1} {##2} } + } + } + \__cs_tmp:w } - \cs_set_protected:Npn \tl_gset:Nn #1#2 + \__cs_tmp:w + \tl_set:Nn \tl_set:No \tl_set:Nx + \tl_gset:Nn \tl_gset:No \tl_gset:Nx + \tl_put_left:Nn \tl_put_left:NV + \tl_put_left:No \tl_put_left:Nx + \tl_gput_left:Nn \tl_gput_left:NV + \tl_gput_left:No \tl_gput_left:Nx + \tl_put_right:Nn \tl_put_right:NV + \tl_put_right:No \tl_put_right:Nx + \tl_gput_right:Nn \tl_gput_right:NV + \tl_gput_right:No \tl_gput_right:Nx + ? \q_recursion_stop +% \end{macrocode} +% The two \texttt{set_eq} functions are done by hand as the internals there +% are a bit different. +% \begin{macrocode} + \cs_set_protected:Npn \tl_set_eq:NN #1#2 { \__cs_check_exists:N #1 - \cs_gset_nopar:Npx #1 { \exp_not:n {#2} } + \__cs_check_exists:N #2 + \cs_set_eq:NN #1 #2 } - \cs_set_protected:Npn \tl_gset:Nx #1#2 + \cs_set_protected:Npn \tl_gset_eq:NN #1#2 { \__cs_check_exists:N #1 - \cs_gset_nopar:Npx #1 {#2} + \__cs_check_exists:N #2 + \cs_gset_eq:NN #1 #2 } - \cs_set_protected:Npn \tl_set_eq:NN #1#2 +% \end{macrocode} +% There is also a need to check all three arguments of the +% \texttt{concat} functions: a token list |#2| or |#3| equal to +% \cs{scan_stop:} would lead to problems later on. +% \begin{macrocode} + \cs_set_protected:Npn \tl_concat:NNN #1#2#3 { \__cs_check_exists:N #1 \__cs_check_exists:N #2 - \cs_set_eq:NN #1 #2 + \__cs_check_exists:N #3 + \tl_set:Nx #1 { \exp_not:o {#2} \exp_not:o {#3} } } - \cs_set_protected:Npn \tl_gset_eq:NN #1#2 + \cs_set_protected:Npn \tl_gconcat:NNN #1#2#3 { \__cs_check_exists:N #1 \__cs_check_exists:N #2 - \cs_gset_eq:NN #1 #2 + \__cs_check_exists:N #3 + \tl_gset:Nx #1 { \exp_not:o {#2} \exp_not:o {#3} } } \fi % \end{macrocode} @@ -1355,4 +1389,4 @@ % % \end{implementation} % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx index 6d8f58c86b0..ec718e88d18 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3alloc.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3alloc.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Register allocation} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx index 549ec6de6f8..ede47fd6312 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3basics.dtx 3987 2012-07-15 21:57:39Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3basics.dtx 4069 2012-08-08 23:12:57Z bruno $ {L3 Basic definitions} %</driver|package> %<*driver> @@ -1019,7 +1019,7 @@ % \cs{cs_if_eq:NNTF} \Arg{cs_1} \Arg{cs_2} \Arg{true code} \Arg{false code} % \end{syntax} % Compares the definition of two \meta{control sequences} and -% is logically \texttt{true} the same, \emph{i.e.}~if the have exactly +% is logically \texttt{true} the same, \emph{i.e.}~if they have exactly % the same definition when examined with \cs{cs_show:N}. % \end{function} % @@ -1454,7 +1454,7 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]{\token_to_str:c, \cs_meaning:c} +% \begin{macro}[EXP]{\token_to_meaning:c, \token_to_str:c, \cs_meaning:c} % \begin{macro}{\cs_show:c} % A small number of variants defined by hand. % Some of the necessary functions @@ -1478,6 +1478,7 @@ { \exp_args:Nc \cs_meaning:N {#1} } { \tl_to_str:n {undefined} } } +\tex_let:D \token_to_meaning:c = \cs_meaning:c \etex_protected:D \tex_def:D \cs_show:c { \group_begin: \exp_args:NNc \group_end: \cs_show:N } % \end{macrocode} @@ -1589,6 +1590,15 @@ % % \subsection{Selecting tokens} % +% \begin{variable}{\l__exp_internal_tl} +% Scratch token list variable for \pkg{l3expan}, used by \cs{use:x}, +% used in defining conditionals. We don't use |tl| methods because +% \pkg{l3basics} is loaded earlier. +% \begin{macrocode} +\cs_set_nopar:Npn \l__exp_internal_tl { } +% \end{macrocode} +% \end{variable} +% % \begin{macro}[EXP]{\use:c} % This macro grabs its argument and returns a csname from it. % \begin{macrocode} @@ -1856,41 +1866,44 @@ % defining function. The sixth is the parameters to use (possibly % empty), the seventh is the list of forms to define, the eigth is the % replacement text which we will augment when defining the forms. +% The use of \cs{etex_detokenize:D} makes the later loop more robust. % \begin{macrocode} \cs_set_protected:Npn \__prg_generate_conditional:nnNnnnnn #1#2#3#4#5#6#7#8 { - \if_meaning:w \c_true_bool #3 - \exp_after:wN \use_i:nn - \else: - \exp_after:wN \use_ii:nn - \fi: - { - \__prg_generate_conditional:nnnnnnw - {#4} {#5} {#1} {#2} {#6} {#8} - #7 , , \q_recursion_stop - } - { + \if_meaning:w \c_false_bool #3 \__msg_kernel_error:nnx { kernel } { missing-colon } { \token_to_str:c {#1} } - } + \exp_after:wN \use_none:nn + \fi: + \use:x + { + \exp_not:N \__prg_generate_conditional:nnnnnnw + \exp_not:n { {#4} {#5} {#1} {#2} {#6} {#8} } + \etex_detokenize:D {#7} + \exp_not:n { , \q_recursion_tail , \q_recursion_stop } + } } % \end{macrocode} % Looping through the list of desired forms. First are six arguments % and seventh is the form. Use the form to call the % correct type. If the form does not exist, the \cs{use:c} % construction results in \tn{relax}, and the error message is -% displayed, then \cs{use_none:nnnnnnn} cleans up. Otherwise, the +% displayed (unless the form is empty, to allow for |{T, , F}|), +% then \cs{use_none:nnnnnnn} cleans up. Otherwise, the % error message is removed by the variant form. % \begin{macrocode} \cs_set_protected:Npn \__prg_generate_conditional:nnnnnnw #1#2#3#4#5#6#7 , { - \if_catcode:w \scan_stop: \etex_detokenize:D {#7} \scan_stop: + \if_meaning:w \q_recursion_tail #7 \exp_after:wN \use_none_delimit_by_q_recursion_stop:w \fi: - \use:c { __prg_generate_ \etex_detokenize:D {#7} _form:wnnnnnn } - \__msg_kernel_error:nnxx - { kernel } { conditional-form-unknown } - { \tl_to_str:n {#7} } { \token_to_str:c { #3 : #4 } } + \use:c { __prg_generate_ #7 _form:wnnnnnn } + \tl_if_empty:nF {#7} + { + \__msg_kernel_error:nnxx + { kernel } { conditional-form-unknown } + {#7} { \token_to_str:c { #3 : #4 } } + } \use_none:nnnnnnn \q_stop {#1} {#2} {#3} {#4} {#5} {#6} @@ -1951,35 +1964,44 @@ % \end{macro} % % \begin{macro}{\prg_set_eq_conditional:NNn,\prg_new_eq_conditional:NNn} -% The setting-equal functions. Split the base function to be copied, -% and feed a first auxiliary \Arg{name} \Arg{signature} \meta{boolean} -% \meta{copying~function} \meta{new~function} \Arg{conditions}. -% \begin{macrocode} -\cs_set_protected:Npn \prg_set_eq_conditional:NNn #1#2 +% \begin{macro}[aux]{\__prg_set_eq_conditional:NNNn} +% The setting-equal functions. Split the two functions and feed a +% first auxiliary \Arg{name_1} \Arg{signature_1} \meta{boolean_1} +% \Arg{name_2} \Arg{signature_2} \meta{boolean_2} +% \meta{copying~function} \meta{conditions} |,| \cs{q_recursion_tail} +% |,| \cs{q_recursion_stop} +% \begin{macrocode} +\cs_set_protected_nopar:Npn \prg_set_eq_conditional:NNn + { \__prg_set_eq_conditional:NNNn \cs_set_eq:cc } +\cs_set_protected_nopar:Npn \prg_new_eq_conditional:NNn + { \__prg_set_eq_conditional:NNNn \cs_new_eq:cc } +\cs_set_protected:Npn \__prg_set_eq_conditional:NNNn #1#2#3#4 { - \__cs_split_function:NN #2 \__prg_set_eq_conditional:nnNNNn - \cs_set_eq:cc #1 - } -\cs_set_protected:Npn \prg_new_eq_conditional:NNn #1#2 - { - \__cs_split_function:NN #2 \__prg_set_eq_conditional:nnNNNn - \cs_new_eq:cc #1 + \use:x + { + \exp_not:N \__prg_set_eq_conditional:nnNnnNNw + \__cs_split_function:NN #2 \prg_do_nothing: + \__cs_split_function:NN #3 \prg_do_nothing: + \exp_not:N #1 + \etex_detokenize:D {#4} + \exp_not:n { , \q_recursion_tail , \q_recursion_stop } + } } % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macro}[aux] % { -% \__prg_set_eq_conditional:nnNNNn , % \__prg_set_eq_conditional:nnNnnNNw , % \__prg_set_eq_conditional_loop:nnnnNw % } % \begin{macro}[aux, EXP] % { -% \__prg_conditional_p_form:nnn , -% \__prg_conditional_TF_form:nnn , -% \__prg_conditional_T_form:nnn , -% \__prg_conditional_F_form:nnn , +% \__prg_set_eq_conditional_p_form:nnn , +% \__prg_set_eq_conditional_TF_form:nnn , +% \__prg_set_eq_conditional_T_form:nnn , +% \__prg_set_eq_conditional_F_form:nnn , % } % Split the function to be defined, and setup a manual clist loop over % argument |#6| of the first auxiliary. The second auxiliary receives @@ -1992,12 +2014,6 @@ % step in the loop, make sure that the conditional form we copy is % defined, and copy it, otherwise abort. % \begin{macrocode} -\cs_set_protected:Npn \__prg_set_eq_conditional:nnNNNn #1#2#3#4#5#6 - { - \__cs_split_function:NN #5 \__prg_set_eq_conditional:nnNnnNNw - {#1} {#2} #3 #4 - #6 , \scan_stop: , \q_recursion_stop - } \cs_set_protected:Npn \__prg_set_eq_conditional:nnNnnNNw #1#2#3#4#5#6 { \if_meaning:w \c_false_bool #3 @@ -2014,29 +2030,41 @@ } \cs_set_protected:Npn \__prg_set_eq_conditional_loop:nnnnNw #1#2#3#4#5#6 , { - \if_meaning:w \scan_stop: #6 \scan_stop: + \if_meaning:w \q_recursion_tail #6 \exp_after:wN \use_none_delimit_by_q_recursion_stop:w \fi: - \cs_if_exist:cTF - { \use:c { __prg_conditional_ #6 _form:nn } {#3} {#4} } - { - #5 - { \use:c { __prg_conditional_ #6 _form:nn } {#1} {#2} } - { \use:c { __prg_conditional_ #6 _form:nn } {#3} {#4} } - } - { - \__msg_kernel_error:nnx { kernel } { command-not-defined } + \use:c { __prg_set_eq_conditional_ #6 _form:wNnnnn } + \tl_if_empty:nF {#6} { - \token_to_str:c - { \use:c { __prg_conditional_ #6 _form:nn } {#3} {#4} } + \__msg_kernel_error:nnxx + { kernel } { conditional-form-unknown } + {#6} { \token_to_str:c { #1 : #2 } } } - } + \use_none:nnnnnn + \q_stop + #5 {#1} {#2} {#3} {#4} \__prg_set_eq_conditional_loop:nnnnNw {#1} {#2} {#3} {#4} #5 } -\cs_set:Npn \__prg_conditional_p_form:nn #1#2 { #1 _p : #2 } -\cs_set:Npn \__prg_conditional_TF_form:nn #1#2 { #1 : #2 TF } -\cs_set:Npn \__prg_conditional_T_form:nn #1#2 { #1 : #2 T } -\cs_set:Npn \__prg_conditional_F_form:nn #1#2 { #1 : #2 F } +\cs_set:Npn \__prg_set_eq_conditional_p_form:wNnnnn #1 \q_stop #2#3#4#5#6 + { + \__chk_if_exist_cs:c { #5 _p : #6 } + #2 { #3 _p : #4 } { #5 _p : #6 } + } +\cs_set:Npn \__prg_set_eq_conditional_TF_form:wNnnnn #1 \q_stop #2#3#4#5#6 + { + \__chk_if_exist_cs:c { #5 : #6 TF } + #2 { #3 : #4 TF } { #5 : #6 TF } + } +\cs_set:Npn \__prg_set_eq_conditional_T_form:wNnnnn #1 \q_stop #2#3#4#5#6 + { + \__chk_if_exist_cs:c { #5 : #6 T } + #2 { #3 : #4 T } { #5 : #6 T } + } +\cs_set:Npn \__prg_set_eq_conditional_F_form:wNnnnn #1 \q_stop #2#3#4#5#6 + { + \__chk_if_exist_cs:c { #5 : #6 F } + #2 { #3 : #4 F } { #5 : #6 F } + } % \end{macrocode} % \end{macro} % \end{macro} @@ -3035,6 +3063,20 @@ } % \end{macrocode} % \end{macro} +% +% \begin{macro}{\__prg_break_point:} +% \begin{macro}{\__prg_break:, \__prg_break:n} +% Very simple analogues of \cs{__prg_break_point:Nn} and +% \cs{__prg_map_break:Nn}, for use in fast short-term recursions which +% are not mappings, do not need to support nesting, and in which +% nothing has to be done at the end of the loop. +% \begin{macrocode} +\cs_new_eq:NN \__prg_break_point: \prg_do_nothing: +\cs_new:Npn \__prg_break: #1 \__prg_break_point: { } +\cs_new:Npn \__prg_break:n #1#2 \__prg_break_point: {#1} +% \end{macrocode} +% \end{macro} +% \end{macro} % % \subsection{Deprecated functions} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx index 1fb3ac9454f..fc1ae68b7c2 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx @@ -119,7 +119,7 @@ % \end{macrocode} % \end{macro} % \end{macro} -\GetIdInfo$Id: l3bootstrap.dtx 3986 2012-07-15 19:23:51Z joseph $ +\GetIdInfo$Id: l3bootstrap.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Bootstrap code} %</driver|package> %<*driver> @@ -190,7 +190,7 @@ % % \begin{function}[updated = 2012-06-04]{\GetIdInfo} % \begin{syntax} -% |\RequirePackage{l3names}| +% |\RequirePackage{l3bootstrap}| % \cs{GetIdInfo} |$Id:| \meta{SVN info field} |$| \Arg{description} % \end{syntax} % Extracts all information from a SVN field. Spaces are not @@ -459,10 +459,24 @@ % not to need \cs{ExplSyntaxOn} each time. % \begin{macrocode} %<*package> -\protected\def\ProvidesExplPackage#1#2#3#4% +\protected\def\ProvidesExplPackage {% - \ProvidesPackage{#1}[#2 v#3 #4]% - \ExplSyntaxOn + \@ifpackageloaded{expl3} + {} + {% + \PackageError{expl3} + {Cannot load the expl3 modules separately} + {% + The expl3 modules cannot be loaded separately;\MessageBreak + please \string\usepackage\string{expl3\string} instead.% + }% + }% + \protected\def\ProvidesExplPackage##1##2##3##4% + {% + \ProvidesPackage{##1}[##2 v##3 ##4]% + \ExplSyntaxOn + }% + \ProvidesExplPackage } \protected\def\ProvidesExplClass#1#2#3#4% {% diff --git a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx index b578295ac44..76c7bc04251 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3box.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3box.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Experimental boxes} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx index 8afac7cda1f..e5c2ab164f4 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx @@ -35,7 +35,7 @@ %% % %<*driver|package> -\RequirePackage{l3names} +\RequirePackage{l3bootstrap} \GetIdInfo$Id: l3candidates.dtx 3633 2012-05-12 20:11:32Z joseph $ {L3 Experimental additions to l3kernel} %</driver|package> @@ -363,10 +363,7 @@ % \cs{coffin_resize:Nnn} \meta{coffin} \Arg{width} \Arg{total-height} % \end{syntax} % Resized the \meta{coffin} to \meta{width} and \meta{total-height}, -% both of which should be given as dimension expressions. These may -% include the terms \cs{TotalHeight}, \cs{Height}, \cs{Depth} and -% \cs{Width}, which will evaluate to the appropriate dimensions of -% the \meta{coffin}. +% both of which should be given as dimension expressions. % \end{function} % % \begin{function}{\coffin_rotate:Nn, \coffin_rotate:cn} @@ -398,6 +395,9 @@ % reading one or more lines (until an equal number of left and right % braces are found) from the \meta{stream}. The \meta{inline function} % should consist of code which will receive the \meta{line} as |#1|. +% Note that \TeX{} removes trailing space and tab characters +% (character codes 32 and 9) from every line upon input. \TeX{} also +% ignores any trailing new-line marker from the file it reads. % \end{function} % % \begin{function}[added = 2012-02-11]{\ior_str_map_inline:Nn} @@ -410,6 +410,9 @@ % exception of space characters which are given category code $10$ % (space). The \meta{inline function} should consist of code which % will receive the \meta{line} as |#1|. +% Note that \TeX{} removes trailing space and tab characters +% (character codes 32 and 9) from every line upon input. \TeX{} also +% ignores any trailing new-line marker from the file it reads. % \end{function} % % \begin{function}[added = 2012-06-29]{\ior_map_break:} @@ -1158,22 +1161,11 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_resize:Nnn #1#2#3 { - \dim_compare:nNnTF {#2} > \c_zero_dim - { \dim_set:Nn \l_@@_right_new_dim {#2} } - { \dim_set:Nn \l_@@_right_new_dim { \c_zero_dim - ( #2 ) } } - \dim_compare:nNnTF {#3} > \c_zero_dim - { - \dim_set:Nn \l_@@_top_new_dim - { \fp_use:N \l_@@_scale_y_fp \l_@@_top_dim } - \dim_set:Nn \l_@@_bottom_new_dim - { \fp_use:N \l_@@_scale_y_fp \l_@@_bottom_dim } - } - { - \dim_set:Nn \l_@@_top_new_dim - { - \fp_use:N \l_@@_scale_y_fp \l_@@_top_dim } - \dim_set:Nn \l_@@_bottom_new_dim - { - \fp_use:N \l_@@_scale_y_fp \l_@@_bottom_dim } - } + \dim_set:Nn \l_@@_right_new_dim { \dim_abs:n {#2} } + \dim_set:Nn \l_@@_bottom_new_dim + { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_bottom_dim } + \dim_set:Nn \l_@@_top_new_dim + { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_top_dim } \@@_resize_common:N #1 } % \end{macrocode} @@ -1230,13 +1222,12 @@ % \end{macro} % % \begin{macro}{\box_scale:Nnn, \box_scale:cnn} -% \begin{macro}[aux]{\@@_scale:Nnn} % When scaling a box, setting the scaling itself is easy enough. The % new dimensions are also relatively easy to find, allowing only for % the need to keep them positive in all cases. Once that is done then % after a check for the trivial scaling a hand-off can be made to the % common code. The dimension scaling operations are carried out using -% the \TeX{} mechanism as it avoids needing to use \texttt{fp} +% the \TeX{} mechanism as it avoids needing to use too many \texttt{fp} % operations. % \begin{macrocode} \cs_new_protected:Npn \box_scale:Nnn #1#2#3 @@ -1250,30 +1241,19 @@ \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 } \dim_set:Nn \l_@@_right_dim { \box_wd:N #1 } \dim_zero:N \l_@@_left_dim - \@@_scale:Nnn #1 {#2} {#3} + \dim_set:Nn \l_@@_top_new_dim + { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_top_dim } + \dim_set:Nn \l_@@_bottom_new_dim + { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_bottom_dim } + \dim_set:Nn \l_@@_right_new_dim + { \fp_abs:n { \l_@@_scale_x_fp } \l_@@_right_dim } + \@@_resize_common:N #1 \group_end: } } \cs_generate_variant:Nn \box_scale:Nnn { c } -\cs_new_protected:Npn \@@_scale:Nnn #1#2#3 - { - \fp_compare:nNnTF \l_@@_scale_y_fp > \c_zero_fp - { - \dim_set:Nn \l_@@_top_new_dim { #3 \l_@@_top_dim } - \dim_set:Nn \l_@@_bottom_new_dim { #3 \l_@@_bottom_dim } - } - { - \dim_set:Nn \l_@@_top_new_dim { -#3 \l_@@_bottom_dim } - \dim_set:Nn \l_@@_bottom_new_dim { -#3 \l_@@_top_dim } - } - \fp_compare:nNnTF \l_@@_scale_x_fp > \c_zero_fp - { \l_@@_right_new_dim #2 \l_@@_right_dim } - { \l_@@_right_new_dim -#2 \l_@@_right_dim } - \@@_resize_common:N #1 - } % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macro}[aux]{\@@_resize_common:N} % The main resize function places in input into a box which will start @@ -1970,12 +1950,13 @@ % \begin{macrocode} \cs_new_protected:Npn \coffin_resize:Nnn #1#2#3 { - \@@_set_user_dimensions:N #1 - \box_resize:Nnn #1 {#2} {#3} \fp_set:Nn \l_@@_scale_x_fp - { \dim_to_fp:n {#2} / \dim_to_fp:n \Width } + { \dim_to_fp:n {#2} / \dim_to_fp:n { \coffin_wd:N #1 } } \fp_set:Nn \l_@@_scale_y_fp - { \dim_to_fp:n {#3} / \dim_to_fp:n \TotalHeight } + { + \dim_to_fp:n {#3} / \dim_to_fp:n { \coffin_ht:N #1 + \coffin_dp:N #1 } + } + \box_resize:Nnn #1 {#2} {#3} \@@_resize_common:Nnn #1 {#2} {#3} } \cs_generate_variant:Nn \coffin_resize:Nnn { c } @@ -2003,7 +1984,6 @@ \prop_map_inline:cn { l_@@_poles_ \__int_value:w #1 _prop } { \@@_x_shift_pole:Nnnnnn #1 {##1} ##2 } } - \@@_end_user_dimensions: } % \end{macrocode} % \end{macro} @@ -2017,16 +1997,15 @@ % \begin{macrocode} \cs_new_protected:Npn \coffin_scale:Nnn #1#2#3 { - \box_scale:Nnn #1 {#2} {#3} - \@@_set_user_dimensions:N #1 \fp_set:Nn \l_@@_scale_x_fp {#2} \fp_set:Nn \l_@@_scale_y_fp {#3} - \fp_compare:nNnTF \l_@@_scale_y_fp > \c_zero_fp - { \l_@@_scaled_total_height_dim #3 \TotalHeight } - { \l_@@_scaled_total_height_dim -#3 \TotalHeight } - \fp_compare:nNnTF \l_@@_scale_x_fp > \c_zero_fp - { \l_@@_scaled_width_dim -#2 \Width } - { \l_@@_scaled_width_dim #2 \Width } + \box_scale:Nnn #1 { \l_@@_scale_x_fp } { \l_@@_scale_y_fp } + \dim_set:Nn \l_@@_internal_dim + { \coffin_ht:N #1 + \coffin_dp:N #1 } + \dim_set:Nn \l_@@_scaled_total_height_dim + { \fp_abs:n { \l_@@_scale_y_fp } \l_@@_internal_dim } + \dim_set:Nn \l_@@_scaled_width_dim + { -\fp_abs:n { \l_@@_scale_x_fp } \coffin_wd:N #1 } \@@_resize_common:Nnn #1 { \l_@@_scaled_width_dim } { \l_@@_scaled_total_height_dim } } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx index 5fbb63f89d9..c7493dc6846 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx @@ -36,8 +36,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3clist.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3clist.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Comma separated lists} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx index b4242b6d8ed..cc205d5da4a 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx @@ -35,8 +35,8 @@ %% % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3coffins.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3coffins.dtx 4011 2012-07-20 21:02:59Z joseph $ {L3 Coffin code layer} %</driver|package> %<*driver> @@ -160,7 +160,7 @@ % environment in a coffin. % \end{function} % -% \begin{function}[added = 2011-08-17] +% \begin{function}[added = 2012-07-20] % {\coffin_set_horizontal_pole:Nnn, \coffin_set_horizontal_pole:cnn} % \begin{syntax} % \cs{coffin_set_horizontal_pole:Nnn} \meta{coffin} @@ -169,13 +169,10 @@ % Sets the \meta{pole} to run horizontally through the \meta{coffin}. % The \meta{pole} will be located at the \meta{offset} from the % bottom edge of the bounding box of the \meta{coffin}. The -% \meta{offset} should be given as a dimension expression; this may -% include the terms \cs{TotalHeight}, \cs{Height}, \cs{Depth} and -% \cs{Width}, which will evaluate to the appropriate dimensions of -% the \meta{coffin}. +% \meta{offset} should be given as a dimension expression. % \end{function} % -% \begin{function}[added = 2011-08-17] +% \begin{function}[added = 2012-07-20] % {\coffin_set_vertical_pole:Nnn, \coffin_set_vertical_pole:cnn} % \begin{syntax} % \cs{coffin_set_vertical_pole:Nnn} \meta{coffin} \Arg{pole} \Arg{offset} @@ -183,10 +180,7 @@ % Sets the \meta{pole} to run vertically through the \meta{coffin}. % The \meta{pole} will be located at the \meta{offset} from the % left-hand edge of the bounding box of the \meta{coffin}. The -% \meta{offset} should be given as a dimension expression; this may -% include the terms \cs{TotalHeight}, \cs{Height}, \cs{Depth} and -% \cs{Width}, which will evaluate to the appropriate dimensions of -% the \meta{coffin}. +% \meta{offset} should be given as a dimension expression. % \end{function} % % \section{Joining and using coffins} @@ -239,15 +233,16 @@ % expressions. % \end{function} % -% \begin{function}{\coffin_typeset:Nnnnn, \coffin_typeset:cnnnn} +% \begin{function}[updated = 2012-07-20] +% {\coffin_typeset:Nnnnn, \coffin_typeset:cnnnn} % \begin{syntax} % \cs{coffin_typeset:Nnnnn} \meta{coffin} \Arg{pole_1} \Arg{pole_2} % ~~\Arg{x-offset} \Arg{y-offset} % \end{syntax} % Typesetting is carried out by first calculating \meta{handle}, the % point of intersection of \meta{pole_1} and \meta{pole_2}. The coffin -% is then typeset such that the relationship between the current -% reference point in the document and the \meta{handle} is described +% is then typeset in horizontal mode such that the relationship between the +% current reference point in the document and the \meta{handle} is described % by the \meta{x-offset} and \meta{y-offset}. The two offsets should % be given as dimension expressions. Typesetting a coffin is % therefore analogous to carrying out an alignment where the @@ -464,39 +459,6 @@ % \end{variable} % \end{variable} % -% \begin{variable}{\l_@@_Depth_dim} -% \begin{variable}{\l_@@_Height_dim} -% \begin{variable}{\l_@@_TotalHeight_dim} -% \begin{variable}{\l_@@_Width_dim} -% Dimensions for the various parts of a coffin. -% \begin{macrocode} -\dim_new:N \l_@@_Depth_dim -\dim_new:N \l_@@_Height_dim -\dim_new:N \l_@@_TotalHeight_dim -\dim_new:N \l_@@_Width_dim -% \end{macrocode} -% \end{variable} -% \end{variable} -% \end{variable} -% \end{variable} -% -% \begin{macro}{\@@_saved_Depth:} -% \begin{macro}{\@@_saved_Height:} -% \begin{macro}{\@@_saved_TotalHeight:} -% \begin{macro}{\@@_saved_Width:} -% Used to save the meaning of \cs{Depth}, \cs{Height}, \cs{TotalHeight} -% and \cs{Width}. -% \begin{macrocode} -\cs_new_nopar:Npn \@@_saved_Depth: { } -\cs_new_nopar:Npn \@@_saved_Height: { } -\cs_new_nopar:Npn \@@_saved_TotalHeight: { } -\cs_new_nopar:Npn \@@_saved_Width: { } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% % \subsection{Basic coffin functions} % % There are a number of basic functions needed for creating coffins and @@ -829,45 +791,6 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_set_user_dimensions:N} -% \begin{macro}{\@@_end_user_dimensions:} -% \begin{macro}{\Depth} -% \begin{macro}{\Height} -% \begin{macro}{\TotalHeight} -% \begin{macro}{\Width} -% These make design-level names for the dimensions of a coffin easy to -% get at. -% \begin{macrocode} -\cs_new_protected:Npn \@@_set_user_dimensions:N #1 - { - \cs_set_eq:NN \@@_saved_Height: \Height - \cs_set_eq:NN \@@_saved_Depth: \Depth - \cs_set_eq:NN \@@_saved_TotalHeight: \TotalHeight - \cs_set_eq:NN \@@_saved_Width: \Width - \cs_set_eq:NN \Height \l_@@_Height_dim - \cs_set_eq:NN \Depth \l_@@_Depth_dim - \cs_set_eq:NN \TotalHeight \l_@@_TotalHeight_dim - \cs_set_eq:NN \Width \l_@@_Width_dim - \dim_set:Nn \Height { \box_ht:N #1 } - \dim_set:Nn \Depth { \box_dp:N #1 } - \dim_set:Nn \TotalHeight { \box_ht:N #1 + \box_dp:N #1 } - \dim_set:Nn \Width { \box_wd:N #1 } - } -\cs_new_protected_nopar:Npn \@@_end_user_dimensions: - { - \cs_set_eq:NN \Height \@@_saved_Height: - \cs_set_eq:NN \Depth \@@_saved_Depth: - \cs_set_eq:NN \TotalHeight \@@_saved_TotalHeight: - \cs_set_eq:NN \Width \@@_saved_Width: - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% % \begin{macro} % {\coffin_set_horizontal_pole:Nnn, \coffin_set_horizontal_pole:cnn} % \begin{macro}{\coffin_set_vertical_pole:Nnn,\coffin_set_vertical_pole:cnn} @@ -881,26 +804,22 @@ { \@@_if_exist:NT #1 { - \@@_set_user_dimensions:N #1 \@@_set_pole:Nnx #1 {#2} { { 0 pt } { \dim_eval:n {#3} } { 1000 pt } { 0 pt } } - \@@_end_user_dimensions: } } \cs_new_protected:Npn \coffin_set_vertical_pole:Nnn #1#2#3 { \@@_if_exist:NT #1 { - \@@_set_user_dimensions:N #1 \@@_set_pole:Nnx #1 {#2} { { \dim_eval:n {#3} } { 0 pt } { 0 pt } { 1000 pt } } - \@@_end_user_dimensions: } } \cs_new_protected:Npn \@@_set_pole:Nnn #1#2#3 @@ -1431,9 +1350,9 @@ % \begin{macrocode} \cs_new_protected:Npn \coffin_typeset:Nnnnn #1#2#3#4#5 { + \hbox_unpack:N \c_empty_box \@@_align:NnnNnnnnN \c_empty_coffin { H } { l } #1 {#2} {#3} {#4} {#5} \l_@@_aligned_coffin - \hbox_unpack:N \c_empty_box \box_use:N \l_@@_aligned_coffin } \cs_generate_variant:Nn \coffin_typeset:Nnnnn { c } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3color.dtx b/Master/texmf-dist/source/latex/l3kernel/l3color.dtx index e8aa1f5d050..3b1476f3714 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3color.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3color.dtx @@ -35,8 +35,8 @@ %% % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3color.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3color.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Experimental colour support} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx index 137d75f056f..8e0c1fd39e8 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx @@ -38,7 +38,7 @@ \ifx\fmtname\nameofplainTeX\else \expandafter\begingroup \fi -\input docstrip.tex +\input l3docstrip.tex \askforoverwritefalse \preamble @@ -78,7 +78,7 @@ Do not distribute a modified version of this file. %</driver|class> % %<*driver|class> -\GetIdInfo$Id: l3doc.dtx 3989 2012-07-16 01:15:43Z bruno $ +\GetIdInfo$Id: l3doc.dtx 4070 2012-08-09 11:04:46Z joseph $ {L3 Experimental documentation class} %</driver|class> % @@ -463,85 +463,71 @@ Do not distribute a modified version of this file. %<*class> % \end{macrocode} % +% \begin{macrocode} +%<@@=codedoc> +% \end{macrocode} +% % \subsection{Variables} % % \begin{macrocode} -\coffin_new:N \l_doc_output_box -\coffin_new:N \l_doc_names_coffin -\coffin_new:N \l_doc_descr_coffin -\coffin_new:N \l_doc_syntax_coffin -\bool_new:N \l_doc_long_name_bool -\bool_new:N \g_doc_implementation_bool -\dim_new:N \l_doc_trial_width_dim -\tl_new:N \l_doc_macro_tl -\int_new:N \l_doc_macro_int -\int_new:N \g_doc_nested_macro_int -\prop_new:N \g_doc_missing_tests_prop +\coffin_new:N \l_@@_output_box +\coffin_new:N \l_@@_names_coffin +\coffin_new:N \l_@@_descr_coffin +\coffin_new:N \l_@@_syntax_coffin +\box_new:N \g_@@_syntax_box +\bool_new:N \l_@@_long_name_bool +\bool_new:N \g_@@_implementation_bool +\dim_new:N \l_@@_trial_width_dim +\tl_new:N \l_@@_macro_tl +\int_new:N \l_@@_macro_int +\int_new:N \g_@@_nested_macro_int +\int_new:N \g_@@_codeline_int +\prop_new:N \g_@@_missing_tests_prop \clist_new:N \g_docinput_clist +\tl_new:N \l_@@_at_replaced_macro_tl % \end{macrocode} % % \begin{macrocode} -\seq_new:N \g_doc_testfiles_seq +\seq_new:N \g_@@_testfiles_seq \seq_new:N \g_doc_functions_seq \seq_new:N \g_doc_macros_seq -\seq_new:N \g_doc_not_tested_seq +\seq_new:N \g_@@_not_tested_seq % \end{macrocode} % % For function/macro environments: % \begin{macrocode} -\bool_new:N \l_doc_meta_TF_bool -\bool_new:N \l_doc_meta_pTF_bool -\bool_new:N \l_doc_meta_EXP_bool -\bool_new:N \l_doc_meta_rEXP_bool -\bool_new:N \l_doc_macro_internal_bool -\bool_new:N \l_doc_macro_aux_bool -\bool_new:N \l_doc_macro_TF_bool -\bool_new:N \l_doc_macro_pTF_bool -\bool_new:N \l_doc_macro_var_bool +\bool_new:N \l_@@_meta_TF_bool +\bool_new:N \l_@@_meta_pTF_bool +\bool_new:N \l_@@_meta_EXP_bool +\bool_new:N \l_@@_meta_rEXP_bool +\bool_new:N \l_@@_macro_internal_bool +\bool_new:N \l_@@_macro_aux_bool +\bool_new:N \l_@@_macro_TF_bool +\bool_new:N \l_@@_macro_pTF_bool +\bool_new:N \l_@@_macro_var_bool % \end{macrocode} % % For package options: % \begin{macrocode} -\bool_new:N \g_doc_full_bool -\bool_new:N \g_doc_lmodern_bool -\bool_new:N \g_doc_checkfunc_bool -\bool_new:N \g_doc_checktest_bool +\bool_new:N \g_@@_full_bool +\bool_new:N \g_@@_lmodern_bool +\bool_new:N \g_@@_checkfunc_bool +\bool_new:N \g_@@_checktest_bool % \end{macrocode} % % Temporaries: % \begin{macrocode} -\seq_new:N \g_doc_tmpa_seq -\tl_new:N \l_doc_tmpa_tl -\tl_new:N \l_doc_tmpb_tl -\int_new:N \l_doc_tmpa_int +\seq_new:N \g_@@_tmpa_seq +\tl_new:N \l_@@_tmpa_tl +\tl_new:N \l_@@_tmpb_tl +\int_new:N \l_@@_tmpa_int % \end{macrocode} % % Other: % \begin{macrocode} -\bool_new:N \l_doc_tested_bool +\bool_new:N \l_@@_tested_bool % \end{macrocode} % -% \subsection{expl3 extras} -% -% \begin{macro} -% { -% \coffin_gset_eq:NN, \coffin_gset_eq:Nc, -% \coffin_gset_eq:cN, \coffin_gset_eq:cc -% } -% Setting two coffins equal is just a wrapper around other functions. -% Slightly naughty use of an internal coffin function here, but \ldots -% \begin{macrocode} -\cs_set_protected_nopar:Npn \coffin_gset_eq:NN #1#2 - { - \coffin_if_exist:NT #1 - { - \box_gset_eq:NN #1 #2 - \__coffin_gset_eq_structure:NN #1 #2 - } - } -\cs_generate_variant:Nn \coffin_gset_eq:NN { c , Nc , cc } -% \end{macrocode} -% \end{macro} % % % \subsection{Options and configuration} @@ -552,23 +538,23 @@ Do not distribute a modified version of this file. % % % \begin{macrocode} -\DeclareOption{full}{ \bool_set_true:N \g_doc_full_bool } -\DeclareOption{onlydoc}{ \bool_set_false:N \g_doc_full_bool } +\DeclareOption{full}{ \bool_set_true:N \g_@@_full_bool } +\DeclareOption{onlydoc}{ \bool_set_false:N \g_@@_full_bool } % \end{macrocode} % % \begin{macrocode} -\DeclareOption{check}{ \bool_set_true:N \g_doc_checkfunc_bool } -\DeclareOption{nocheck}{ \bool_set_false:N \g_doc_checkfunc_bool } +\DeclareOption{check}{ \bool_set_true:N \g_@@_checkfunc_bool } +\DeclareOption{nocheck}{ \bool_set_false:N \g_@@_checkfunc_bool } % \end{macrocode} % % \begin{macrocode} -\DeclareOption{checktest}{ \bool_set_true:N \g_doc_checktest_bool } -\DeclareOption{nochecktest}{ \bool_set_false:N \g_doc_checktest_bool } +\DeclareOption{checktest}{ \bool_set_true:N \g_@@_checktest_bool } +\DeclareOption{nochecktest}{ \bool_set_false:N \g_@@_checktest_bool } % \end{macrocode} % % \begin{macrocode} -\DeclareOption{cm-default}{ \bool_set_false:N \g_doc_lmodern_bool } -\DeclareOption{lm-default}{ \bool_set_true:N \g_doc_lmodern_bool } +\DeclareOption{cm-default}{ \bool_set_false:N \g_@@_lmodern_bool } +\DeclareOption{lm-default}{ \bool_set_true:N \g_@@_lmodern_bool } % \end{macrocode} % % \begin{macrocode} @@ -580,14 +566,14 @@ Do not distribute a modified version of this file. % % \begin{macrocode} \msg_new:nnn {l3doc} {input-cfg} - { - Local~config~file~l3doc.cfg~loaded. - } + { + Local~config~file~l3doc.cfg~loaded. + } \file_if_exist:nT {l3doc.cfg} - { - \file_input:n {l3doc.cfg} - \msg_info:nn {l3doc} {input-cfg} - } + { + \file_input:n {l3doc.cfg} + \msg_info:nn {l3doc} {input-cfg} + } % \end{macrocode} % % \begin{macrocode} @@ -609,13 +595,15 @@ Do not distribute a modified version of this file. color, colortbl, fixltx2e, + hologo, enumitem, pifont, textcomp, trace, underscore, csquotes, - fancyvrb + fancyvrb, + verbatim } \raggedbottom % \end{macrocode} @@ -630,57 +618,36 @@ Do not distribute a modified version of this file. % \end{macrocode} % % \begin{macrocode} -\bool_if:NT \g_doc_lmodern_bool { +\bool_if:NT \g_@@_lmodern_bool + { \RequirePackage[T1]{fontenc} \RequirePackage{lmodern} % \end{macrocode} % Now replace the italic typewriter font with the oblique shape instead; % the former makes my skin crawl. (Will, Aug 2011) % \begin{macrocode} - \begingroup + \group_begin: \ttfamily \DeclareFontShape{T1}{lmtt}{m}{it}{<->ec-lmtto10}{} - \endgroup -} + \group_end: + } % \end{macrocode} % +% Must be last, as usual. % \begin{macrocode} \RequirePackage{hypdoc} % \end{macrocode} -% Just want the "comment" environment from \pkg{verbatim}: -% \begin{macrocode} -\let\doc@verbatim\verbatim -\let\enddoc@verbatim\endverbatim -\let\doc@@verbatim\@verbatim -\expandafter\let\csname doc@verbatim*\expandafter\endcsname - \csname verbatim*\endcsname -\expandafter\let\csname enddoc@verbatim*\expandafter\endcsname - \csname endverbatim*\endcsname -\expandafter\let\csname doc@@verbatim*\expandafter\endcsname - \csname @verbatim*\endcsname -\RequirePackage{verbatim} -\AtBeginDocument{% - \let\verbatim\doc@verbatim - \let\endverbatim\enddoc@verbatim - \let\@verbatim\doc@@verbatim - \expandafter\let\csname verbatim*\expandafter\endcsname - \csname doc@verbatim*\endcsname - \expandafter\let\csname endverbatim*\expandafter\endcsname - \csname enddoc@verbatim*\endcsname - \expandafter\let\csname @verbatim*\expandafter\endcsname - \csname doc@@verbatim*\endcsname -} -% \end{macrocode} % % \subsection{Configuration} % % \begin{macro}{\MakePrivateLetters} % \begin{macrocode} -\cs_set_nopar:Npn \MakePrivateLetters { +\cs_set_nopar:Npn \MakePrivateLetters + { \char_set_catcode_letter:N \@ \char_set_catcode_letter:N \_ \char_set_catcode_letter:N \: -} + } % \end{macrocode} % \end{macro} % @@ -712,18 +679,19 @@ Do not distribute a modified version of this file. % % Customise lists: % \begin{macrocode} -\cs_set_eq:NN \@@oldlist\list -\cs_set_nopar:Npn \list#1#2{\@@oldlist{#1}{#2\listparindent\z@}} +\cs_set_eq:NN \@@_oldlist:nn \list +\cs_set_nopar:Npn \list #1 #2 { \@@_oldlist:nn {#1} { #2 \listparindent\z@ } } \setlength \parindent { 2em } \setlength \itemindent { 0pt } \setlength \parskip { 0pt plus 3pt minus 0pt } % \end{macrocode} % -% % Customise TOC (as we have so many sections). Different design and/or % structure is called for ): % \begin{macrocode} -\cs_set_nopar:Npn \l@section #1#2 { +\@addtoreset{section}{part} +\cs_set_nopar:Npn \l@section #1#2 + { \ifnum \c@tocdepth >\z@ \addpenalty\@secpenalty \addvspace{1.0em \@plus\p@} @@ -736,7 +704,8 @@ Do not distribute a modified version of this file. \hskip -\leftskip #1\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par \endgroup - \fi} + \fi + } \cs_set_nopar:Npn\l@subsection{\@dottedtocline{2}{2.5em}{2.3em}} % #2 = 1.5em % \end{macrocode} % @@ -747,26 +716,20 @@ Do not distribute a modified version of this file. % the document preamble, where an active character may interfere % with packages that are loaded. % \begin{macrocode} -\AtBeginDocument { +\AtBeginDocument + { \MakeShortVerb \" \MakeShortVerb \| -} + } % \end{macrocode} % % \begin{macrocode} -\providecommand*\eTeX{ - \if b\expandafter\@car\f@series\@nil\boldmath\fi - $\m@th\varepsilon$-\TeX -} -\providecommand*\IniTeX{Ini\TeX} +\providecommand*\eTeX{\hologo{eTeX}} +\providecommand*\IniTeX{\hologo{iniTeX}} \providecommand*\Lua{Lua} -\providecommand*\LuaTeX{\Lua\TeX} -\providecommand*\pdfTeX{pdf\TeX} -\RequirePackage{graphicx} -\cs_if_free:NT \XeTeX { - \cs_new_protected_nopar:Npn \XeTeX - {X\kern-.125em\lower.5ex\hbox{\reflectbox{E}}\kern-.1667em\TeX} -} +\providecommand*\LuaTeX{\hologo{LuaTeX}} +\providecommand*\pdfTeX{\hologo{pdfTeX}} +\providecommand*\XeTeX{\hologo{XeTeX}} % \end{macrocode} % % \begin{macro}{\cmd,\cs} @@ -775,23 +738,32 @@ Do not distribute a modified version of this file. % syntax. There is a bit of shuffling around to make sure that |_| % has the catcode that \cs{doc_replace_at_at:N} expects, without % rescanning the whole argument. For that we store in -% \cs{l_doc_tmpb_tl} a single underscore with the current catcode, +% \cs{l_@@_tmpb_tl} a single underscore with the current catcode, % then replace all such underscores by letter underscores in |#1| % (stored in the |tmpa| token list). After calling % \cs{doc_replace_at_at:N}, we replace the underscores back to their % old meaning before using the token list. % \begin{macrocode} -\cs_set_nopar:Npn \cmd #1 { \cs{\expandafter \doc_cmd_to_cs:w \string#1} } -\cs_set_nopar:Npn \doc_cmd_to_cs:w #1#2 { \char\number`#2\relax } -\DeclareRobustCommand \cs [1] - { - \tl_set_rescan:Nnn \l_doc_tmpb_tl { } { _ } - \tl_set:Nn \l_doc_tmpa_tl {#1} - \tl_replace_all:NVn \l_doc_tmpa_tl \l_doc_tmpb_tl { _ } - \doc_replace_at_at:N \l_doc_tmpa_tl - \tl_replace_all:NnV \l_doc_tmpa_tl { _ } \l_doc_tmpb_tl - \texttt { \char`\\ \tl_use:N \l_doc_tmpa_tl} - } +\DeclareDocumentCommand \cmd {m} { \@@_cmd:n { #1 } } +\DeclareDocumentCommand \cs {m} { \@@_cs:n { #1 } } +% \end{macrocode} +% +% This is |\cmd{\foo}| and |\cs{foo}|: \cmd\foo\ and \cs{foo}. +% \begin{macrocode} +\cs_new:Npn \@@_cmd:n #1 { \cs{ \expandafter \@@_cmd_to_cs:w \string#1 } } +\cs_set_nopar:Npn \@@_cmd_to_cs:w #1#2 { \char\number`#2\relax } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Npn \@@_cs:n #1 + { + \tl_set_rescan:Nnn \l_@@_tmpb_tl { } { _ } + \tl_set:Nn \l_@@_tmpa_tl {#1} + \tl_replace_all:NVn \l_@@_tmpa_tl \l_@@_tmpb_tl { _ } + \@@_replace_at_at:N \l_@@_tmpa_tl + \tl_replace_all:NnV \l_@@_tmpa_tl { _ } \l_@@_tmpb_tl + \texttt { \char`\\ \tl_use:N \l_@@_tmpa_tl} + } \cs_generate_variant:Nn \tl_replace_all:Nnn { NV , NnV } % \end{macrocode} % \end{macro} @@ -819,13 +791,15 @@ Do not distribute a modified version of this file. % % \begin{environment}{texnote} % \begin{macrocode} -\newenvironment{texnote}{ +\newenvironment{texnote} + { \endgraf \vspace{3mm} \small\textbf{\TeX~hackers~note:} -}{ + } + { \vspace{3mm} -} + } % \end{macrocode} % \end{environment} % @@ -833,11 +807,16 @@ Do not distribute a modified version of this file. % As \cs{cs}. Use this to mark up all \TeX\ and \LaTeXe\ commands; they % then end up together in the index. TODO: hyperlinks in the index entries. % \begin{macrocode} -\newcommand\tn[1]{ +\DeclareDocumentCommand \tn {m} + { \texttt { \char`\\ #1 } - \index{TeX~and~LaTeX2e~commands\actualchar - \string\TeX{}~and~\string\LaTeXe{}~commands:\levelchar - #1\actualchar{\string\ttfamily\string\bslash{}#1}}} + \index + { + TeX~and~LaTeX2e~commands\actualchar + \string\TeX{}~and~\string\LaTeXe{}~commands:\levelchar + #1\actualchar{\string\ttfamily\string\bslash{}#1} + } + } % \end{macrocode} % \end{macro} % @@ -846,31 +825,40 @@ Do not distribute a modified version of this file. % \begin{macro}{\EnableDocumentation,\EnableImplementation} % \begin{macro}{\DisableDocumentation,\DisableImplementation} % \begin{macrocode} -\cs_new:Npn \doc_implementation: { - \DeclareDocumentCommand {\variable} { O{} } { \doc_macro:n { var , ##1 } } +\cs_new:Npn \@@_implementation: + { + \DeclareDocumentCommand {\variable} { O{} } { \@@_macro:n { var , ##1 } } \cs_set_eq:NN \endvariable \endmacro -} -\cs_new:Npn \doc_docu: { + } +\cs_new:Npn \@@_docu: + { \cs_set_eq:NN \variable \variabledoc \cs_set_eq:NN \endvariable \endvariabledoc -} -\AtEndOfPackage{\doc_docu:} -\newenvironment{documentation}{\doc_docu:}{} -\newenvironment{implementation}{\doc_implementation:}{} -\newcommand\EnableDocumentation{% - \renewenvironment{documentation}{\doc_docu:}{}% -} -\newcommand\EnableImplementation{% - \renewenvironment{implementation}{\doc_implementation:}{}% -} -\newcommand\DisableDocumentation{% + } +\AtEndOfPackage{\@@_docu:} +\newenvironment{documentation}{\@@_docu:}{} +\newenvironment{implementation}{\@@_implementation:}{} +% \end{macrocode} +% +% \begin{macrocode} +\NewDocumentCommand \EnableDocumentation {} + { + \renewenvironment{documentation}{\@@_docu:}{} + } +\NewDocumentCommand \EnableImplementation {} + { + \renewenvironment{implementation}{\@@_implementation:}{} + } +\NewDocumentCommand \DisableDocumentation {} + { \cs_set_eq:NN \documentation \comment \cs_set_eq:NN \enddocumentation \endcomment -} -\newcommand\DisableImplementation{% + } +\NewDocumentCommand \DisableImplementation {} + { \cs_set_eq:NN \implementation \comment \cs_set_eq:NN \endimplementation \endcomment -} + } % \end{macrocode} % \end{macro} % \end{macro} @@ -881,44 +869,47 @@ Do not distribute a modified version of this file. % This environment is designed to be used within a \env{macro} environment % to describe the arguments of the macro/function. % \begin{macrocode} -\newenvironment{arguments}{ +\newenvironment{arguments} + { \enumerate[ nolistsep, label=\texttt{\#\arabic*}~:, labelsep=*, ] -}{ + } + { \endenumerate -} + } % \end{macrocode} % \end{environment} % % \begin{macrocode} \keys_define:nn { l3doc/function } - { - TF .code:n = - { - \bool_gset_true:N \l_doc_meta_TF_bool - } , - EXP .code:n = - { - \bool_gset_true:N \l_doc_meta_EXP_bool - \bool_gset_false:N \l_doc_meta_rEXP_bool - } , - rEXP .code:n = - { - \bool_gset_false:N \l_doc_meta_EXP_bool - \bool_gset_true:N \l_doc_meta_rEXP_bool - } , - pTF .code:n = - { - \bool_gset_true:N \l_doc_meta_pTF_bool - \bool_gset_true:N \l_doc_meta_TF_bool - \bool_gset_true:N \l_doc_meta_EXP_bool - } , - added .tl_set:N = \l_doc_date_added_tl , - updated .tl_set:N = \l_doc_date_updated_tl , - } + { + TF .code:n = + { + \bool_gset_true:N \l_@@_meta_TF_bool + } , + EXP .code:n = + { + \bool_gset_true:N \l_@@_meta_EXP_bool + \bool_gset_false:N \l_@@_meta_rEXP_bool + } , + rEXP .code:n = + { + \bool_gset_false:N \l_@@_meta_EXP_bool + \bool_gset_true:N \l_@@_meta_rEXP_bool + } , + pTF .code:n = + { + \bool_gset_true:N \l_@@_meta_pTF_bool + \bool_gset_true:N \l_@@_meta_TF_bool + \bool_gset_true:N \l_@@_meta_EXP_bool + } , + added .tl_set:N = \l_@@_date_added_tl , + updated .tl_set:N = \l_@@_date_updated_tl , + tested .code:n = { } , + } % \end{macrocode} % % @@ -930,23 +921,25 @@ Do not distribute a modified version of this file. % Ignore spaces and sanitize with catcodes before reading argument. % \begin{macrocode} \char_set_catcode_active:N \< -\DeclareDocumentEnvironment {function} { O{} } { +\DeclareDocumentEnvironment {function} { O{} } + { \par\bigskip\noindent \phantomsection - \coffin_clear:N \l_doc_descr_coffin - \coffin_clear:N \l_doc_syntax_coffin - \coffin_clear:N \l_doc_names_coffin + \coffin_clear:N \l_@@_descr_coffin + \box_gclear:N \g_@@_syntax_box + \coffin_clear:N \l_@@_syntax_coffin + \coffin_clear:N \l_@@_names_coffin - \bool_set_false:N \l_doc_meta_TF_bool - \bool_set_false:N \l_doc_meta_pTF_bool - \bool_set_false:N \l_doc_meta_EXP_bool - \bool_set_false:N \l_doc_meta_rEXP_bool + \bool_set_false:N \l_@@_meta_TF_bool + \bool_set_false:N \l_@@_meta_pTF_bool + \bool_set_false:N \l_@@_meta_EXP_bool + \bool_set_false:N \l_@@_meta_rEXP_bool \keys_set:nn { l3doc/function } {#1} - \char_set_active_eq:NN < \doc_open_meta:w + \char_set_active_eq:NN < \@@_open_meta:w \group_begin: \MakePrivateLetters @@ -957,96 +950,101 @@ Do not distribute a modified version of this file. \char_set_catcode_ignore:N \^^I \exp_after:wN \group_end: - \function_aux:n - } - { - \vcoffin_set_end: - \bool_if:NTF \l_doc_long_name_bool - { - \coffin_join:NnnNnnnn - \l_doc_output_box {hc} {vc} - \l_doc_syntax_coffin {l} {T} - {0pt} {0pt} - \coffin_join:NnnNnnnn - \l_doc_output_box {l} {t} - \l_doc_names_coffin {r} {t} - {-\marginparsep} {0pt} - \coffin_join:NnnNnnnn - \l_doc_output_box {l} {b} - \l_doc_descr_coffin {l} {t} - {0.75\marginparwidth + \marginparsep} {-\medskipamount} + \@@_function:n + } + { + \vcoffin_set_end: + \hcoffin_set:Nn \l_@@_syntax_coffin { \box_use:N \g_@@_syntax_box } +% \end{macrocode} +% \cs{g_@@_syntax_box} is defined in the syntax environment. +% \begin{macrocode} + \bool_if:NTF \l_@@_long_name_bool + { + \coffin_join:NnnNnnnn + \l_@@_output_box {hc} {vc} + \l_@@_syntax_coffin {l} {T} + {0pt} {0pt} + \coffin_join:NnnNnnnn + \l_@@_output_box {l} {t} + \l_@@_names_coffin {r} {t} + {-\marginparsep} {0pt} + \coffin_join:NnnNnnnn + \l_@@_output_box {l} {b} + \l_@@_descr_coffin {l} {t} + {0.75\marginparwidth + \marginparsep} {-\medskipamount} - \coffin_typeset:Nnnnn \l_doc_output_box {\l_doc_descr_coffin-l} {\l_doc_descr_coffin-t} {0pt} {0pt} - } - { - \coffin_join:NnnNnnnn - \l_doc_output_box {hc} {vc} - \l_doc_syntax_coffin {l} {t} - {0pt} {0pt} - \coffin_join:NnnNnnnn - \l_doc_output_box {l} {b} - \l_doc_descr_coffin {l} {t} - {0pt} {-\medskipamount} - \coffin_join:NnnNnnnn - \l_doc_output_box {l} {t} - \l_doc_names_coffin {r} {t} - {-\marginparsep} {0pt} + \coffin_typeset:Nnnnn \l_@@_output_box {\l_@@_descr_coffin-l} {\l_@@_descr_coffin-t} {0pt} {0pt} + } + { + \coffin_join:NnnNnnnn + \l_@@_output_box {hc} {vc} + \l_@@_syntax_coffin {l} {t} + {0pt} {0pt} + \coffin_join:NnnNnnnn + \l_@@_output_box {l} {b} + \l_@@_descr_coffin {l} {t} + {0pt} {-\medskipamount} + \coffin_join:NnnNnnnn + \l_@@_output_box {l} {t} + \l_@@_names_coffin {r} {t} + {-\marginparsep} {0pt} - \coffin_typeset:Nnnnn - \l_doc_output_box {\l_doc_syntax_coffin-l} {\l_doc_syntax_coffin-T} - {0pt} {0pt} - } - \par - \allowbreak - } + \coffin_typeset:Nnnnn + \l_@@_output_box {\l_@@_syntax_coffin-l} {\l_@@_syntax_coffin-T} + {0pt} {0pt} + } + \par + \allowbreak + } \char_set_catcode_other:N \< \cs_set_eq:NN \variabledoc \function \cs_set_eq:NN \endvariabledoc \endfunction % \end{macrocode} % % -% \begin{macro}{\function_aux:n} +% \begin{macro}{\@@_function:n} % \begin{arguments} % \item Comma-separated list of functions; % input has already been sanitised by catcode changes before reading % the argument. % \end{arguments} % \begin{macrocode} -\cs_set_nopar:Npn \function_aux:n #1 { +\cs_set_nopar:Npn \@@_function:n #1 + { - \tl_set:Nn \l_doc_function_input_tl {#1} + \tl_set:Nn \l_@@_function_input_tl {#1} - \dim_zero:N \l_doc_trial_width_dim - \hcoffin_set:Nn \l_doc_names_coffin { \function_typeset:n {#1} } - \dim_set:Nn \l_doc_trial_width_dim { \box_wd:N \l_doc_names_coffin } + \dim_zero:N \l_@@_trial_width_dim + \hcoffin_set:Nn \l_@@_names_coffin { \function_typeset:n {#1} } + \dim_set:Nn \l_@@_trial_width_dim { \box_wd:N \l_@@_names_coffin } - \bool_set:Nn \l_doc_long_name_bool - { \dim_compare_p:nNn \l_doc_trial_width_dim > \marginparwidth } + \bool_set:Nn \l_@@_long_name_bool + { \dim_compare_p:nNn \l_@@_trial_width_dim > \marginparwidth } - \vcoffin_set:Nnw \l_doc_descr_coffin {\textwidth} + \vcoffin_set:Nnw \l_@@_descr_coffin {\textwidth} \noindent\ignorespaces -} + } \cs_gset_nopar:Npn \function_typeset:n #1 %^^A todo: use "\cs_new:Npn" here - { - \tl_gclear:N \g_doc_macro_tl + { + \tl_gclear:N \g_@@_macro_tl - % populate "\l_doc_functions_block_prop" with info on the functions present: - \clist_map_function:nN {#1} \doc_parse_functions:n + % populate "\l_@@_functions_block_prop" with info on the functions present: + \clist_map_function:nN {#1} \@@_parse_functions:n - \small\ttfamily - \begin{tabular}{ @{} l @{} r @{} } - \toprule - \prop_map_function:NN \l_doc_functions_block_prop \doc_typeset_functions:nn - \doc_typeset_dates: - \bottomrule - \end{tabular} - \normalfont\normalsize - } + \small\ttfamily + \begin{tabular}{ @{} l @{} r @{} } + \toprule + \prop_map_function:NN \l_@@_functions_block_prop \@@_typeset_functions:nn + \@@_typeset_dates: + \bottomrule + \end{tabular} + \normalfont\normalsize + } % \end{macrocode} % \end{macro} % -% \begin{macro}{\doc_parse_functions:n} -% The idea here is to populate "\l_doc_functions_block_prop" with information +% \begin{macro}{\@@_parse_functions:n} +% The idea here is to populate "\l_@@_functions_block_prop" with information % about the functions being typeset and their variants. % The property list uses a specific format: the keys contained are the function `names' (stripped of signature) with values specified by a comma-separated list containing two brace groups per item: % \begin{center} @@ -1054,289 +1052,311 @@ Do not distribute a modified version of this file. % \end{center} % This somewhat arcane syntax is chosen to distinguish between all variants of control sequence that may be being documented here. (With or without \textsf{expl3} function syntax.) % \begin{macrocode} -\prop_new:N \l_doc_functions_block_prop +\prop_new:N \l_@@_functions_block_prop \cs_generate_variant:Nn \prop_put:Nnn {Nxx} -\cs_new:Nn \doc_parse_functions:n - { - \exp_args:Nxx \tl_if_head_eq_charcode:nNTF { \token_to_str:N #1 } {\cs_to_str:N \\} - { - \tl_gset_eq:NN \l_doc_function_name_prefix_tl \@backslashchar - % for the weird functions named "\::N" and so on: - \exp_args:Nx \tl_if_head_eq_charcode:nNTF { \cs_to_str:N #1 } { : } - { - % again, no variants: - \prop_put:Nxx \l_doc_functions_block_prop { \cs_to_str:N #1 } { {-1} {} } - } - { - % finally, for regular old csnames: - \exp_args:NNf \prop_get:NnNTF - \l_doc_functions_block_prop - { \__cs_get_function_name:N #1 } \l_doc_tmpb_tl - { - \prop_put:Nxx \l_doc_functions_block_prop - { \__cs_get_function_name:N #1 } - { - \l_doc_tmpb_tl , - {\__cs_count_signature:N #1} - {\__cs_get_function_signature:N #1} - } - } - { - \prop_put:Nxx \l_doc_functions_block_prop - { \__cs_get_function_name:N #1 } - { - {\__cs_count_signature:N #1} - {\__cs_get_function_signature:N #1} - } - } - } - } - % for keys and things that aren't actually csnames: - { - % for now don't bother splitting into variants: - \tl_gclear:N \l_doc_function_name_prefix_tl - \prop_put:Nxx \l_doc_functions_block_prop { \tl_to_str:n {#1} } { {-1} {} } - } - } - +\cs_new:Nn \@@_parse_functions:n + { + \exp_args:Nxx \tl_if_head_eq_charcode:nNTF { \token_to_str:N #1 } {\cs_to_str:N \\} + { + \tl_gset_eq:NN \l_@@_function_name_prefix_tl \@backslashchar + % for the weird functions named "\::N" and so on: + \exp_args:Nx \tl_if_head_eq_charcode:nNTF { \cs_to_str:N #1 } { : } + { + % again, no variants: + \prop_put:Nxx \l_@@_functions_block_prop { \cs_to_str:N #1 } { {-1} {} } + } + { + % finally, for regular old csnames: + \exp_args:NNf \prop_get:NnNTF + \l_@@_functions_block_prop + { \__cs_get_function_name:N #1 } \l_@@_tmpb_tl + { + \prop_put:Nxx \l_@@_functions_block_prop + { \__cs_get_function_name:N #1 } + { + \l_@@_tmpb_tl , + {\__cs_count_signature:N #1} + {\__cs_get_function_signature:N #1} + } + } + { + \prop_put:Nxx \l_@@_functions_block_prop + { \__cs_get_function_name:N #1 } + { + {\__cs_count_signature:N #1} + {\__cs_get_function_signature:N #1} + } + } + } + } +% \end{macrocode} +% False branch for keys and things that aren't actually csnames: +% \begin{macrocode} + { + % for now don't bother splitting into variants: + \tl_gclear:N \l_@@_function_name_prefix_tl + \prop_put:Nxx \l_@@_functions_block_prop { \tl_to_str:n {#1} } { {-1} {} } + } + } % \end{macrocode} % \end{macro} % \end{environment} % \end{environment} % % -% \begin{macro}{\doc_typeset_functions:nn} +% \begin{macro}{\@@_typeset_functions:nn} % \begin{arguments} % \item Function/macro/variable name (stripped of signature in the first case, if any) % \item Comma-list containing information about the signature variants being documented (if any) % \end{arguments} % \begin{macrocode} -\cs_new:Nn \doc_typeset_functions:nn - { - \clist_gset:Nn \l_doc_variants_clist {#2} - \clist_gpop:NN \l_doc_variants_clist \l_doc_tmpb_tl - \exp_args:Nc \doc_typeset_functions_aux:N - { - #1 - \int_compare:nT { \exp_after:wN \use_i:nn \l_doc_tmpb_tl > -1 } {:} - \int_compare:nT { \exp_after:wN \use_i:nn \l_doc_tmpb_tl > 0 } - { \exp_after:wN \use_ii:nn \l_doc_tmpb_tl } - } - \\ - } +\cs_new:Nn \@@_typeset_functions:nn + { + \clist_gset:Nn \l_@@_variants_clist {#2} + \clist_gpop:NN \l_@@_variants_clist \l_@@_tmpb_tl + \exp_args:Nc \@@_typeset_functions_aux:N + { + #1 + \int_compare:nT { \exp_after:wN \use_i:nn \l_@@_tmpb_tl > -1 } {:} + \int_compare:nT { \exp_after:wN \use_i:nn \l_@@_tmpb_tl > 0 } + { \exp_after:wN \use_ii:nn \l_@@_tmpb_tl } + } + \\ + } -\cs_new_nopar:Nn \doc_typeset_functions_aux:N -{ - \bool_if:NT \l_doc_meta_pTF_bool { - \tl_set:Nx \l_doc_pTF_name_tl - { \l_doc_function_name_prefix_tl \doc_predicate_from_base:N #1 } - \doc_special_main_index:o { \l_doc_pTF_name_tl } +\cs_new_nopar:Nn \@@_typeset_functions_aux:N + { + \bool_if:NT \l_@@_meta_pTF_bool + { + \tl_set:Nx \l_@@_pTF_name_tl + { \l_@@_function_name_prefix_tl \@@_predicate_from_base:N #1 } + \@@_special_main_index:o { \l_@@_pTF_name_tl } \seq_gput_right:Nx \g_doc_functions_seq - { \tl_to_str:N \l_doc_pTF_name_tl } - \tl_set:Nx \l_doc_pTF_name_tl { \doc_predicate_from_base:N #1 } - } - - \tl_set:Nx \l_doc_tmpa_tl - { - \l_doc_function_name_prefix_tl - \cs_to_str:N #1 - \bool_if:NT \l_doc_meta_TF_bool { \tl_to_str:n {TF} } - } - \doc_special_main_index:o { \l_doc_tmpa_tl } - \seq_gput_right:No \g_doc_functions_seq { \l_doc_tmpa_tl } + { \tl_to_str:N \l_@@_pTF_name_tl } + \tl_set:Nx \l_@@_pTF_name_tl { \@@_predicate_from_base:N #1 } + } - \bool_if:NTF \l_doc_meta_pTF_bool { + \tl_set:Nx \l_@@_tmpa_tl + { + \l_@@_function_name_prefix_tl + \cs_to_str:N #1 + \bool_if:NT \l_@@_meta_TF_bool { \tl_to_str:n {TF} } + } + \@@_special_main_index:o { \l_@@_tmpa_tl } + \seq_gput_right:No \g_doc_functions_seq { \l_@@_tmpa_tl } - \bool_gset_false:N \l_doc_meta_TF_bool - \exp_args:Nc \doc_typeset_function_block:N { \l_doc_pTF_name_tl } - \bool_gset_true:N \l_doc_meta_TF_bool + \bool_if:NTF \l_@@_meta_pTF_bool + { + \bool_gset_false:N \l_@@_meta_TF_bool + \exp_args:Nc \@@_typeset_function_block:N { \l_@@_pTF_name_tl } + \bool_gset_true:N \l_@@_meta_TF_bool \\ - \doc_typeset_function_block:N #1 - - }{ + \@@_typeset_function_block:N #1 + } + { \exp_args:Nx \tl_if_head_eq_charcode:nNTF { \exp_after:wN \use_none:n \token_to_str:N #1 } {:} - { \doc_show_macro_unusual:N #1 } - { \doc_typeset_function_block:N #1 } - } + { \@@_show_macro_unusual:N #1 } + { \@@_typeset_function_block:N #1 } + } } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\doc_typeset_function_block:N} +% \begin{macro}[internal]{\@@_typeset_function_block:N} % \begin{macrocode} -\cs_set_nopar:Nn \doc_typeset_function_block:N { - \tl_gset:Nx \l_doc_function_name_tl { \__cs_get_function_name:N #1 } - \tl_gset:Nx \l_doc_function_sig_tl { \__cs_get_function_signature:N #1 } - \tl_gset:Nx \g_doc_macro_tl { \l_doc_function_name_prefix_tl \l_doc_function_name_tl } - - \doc_typeset_function_basename:N #1 - \bool_if:NT \l_doc_meta_TF_bool { \doc_typeset_TF: } - \doc_typeset_expandability: - \clist_if_empty:NF \l_doc_variants_clist { \doc_typeset_variants: } - \bool_if:NT \g_doc_full_bool { \doc_label_function:N #1 } +\cs_set_nopar:Nn \@@_typeset_function_block:N + { + \tl_gset:Nx \l_@@_function_name_tl { \__cs_get_function_name:N #1 } + \tl_gset:Nx \l_@@_function_sig_tl { \__cs_get_function_signature:N #1 } + \tl_gset:Nx \g_@@_macro_tl { \l_@@_function_name_prefix_tl \l_@@_function_name_tl } -} -\cs_set:Nn \doc_typeset_function_basename:N - { \l_doc_function_name_prefix_tl \cs_to_str:N #1 } -\cs_set:Nn \doc_typeset_expandability: - { - & - \bool_if:NT \l_doc_meta_EXP_bool { - \hspace{\tabcolsep} - \hyperlink{expstar} {$\star$} - } - \bool_if:NT \l_doc_meta_rEXP_bool { - \hspace{\tabcolsep} - \hyperlink{rexpstar} {\ding{73}} % hollow star - } - } -\cs_set:Nn \doc_typeset_variants: - { - \\ - \doc_typeset_aux:n \g_doc_macro_tl : - \int_compare:nTF { \clist_count:N \l_doc_variants_clist == 1 } - { \exp_after:wN \use_ii:nn \l_doc_variants_clist } - { - \textrm( - \clist_pop:NN \l_doc_variants_clist \l_doc_tmpb_tl - \exp_after:wN \use_ii:nn \l_doc_tmpb_tl - \clist_map_inline:Nn \l_doc_variants_clist {\textrm| \use_ii:nn ##1} - \textrm) - } - \bool_if:NT \l_doc_meta_TF_bool { \doc_typeset_TF: } - & - \bool_if:NT \l_doc_meta_EXP_bool { - \hspace{\tabcolsep} - \hyperlink{expstar} {$\star$} - } - \bool_if:NT \l_doc_meta_rEXP_bool { - \hspace{\tabcolsep} - \hyperlink{rexpstar} {\ding{73}} % hollow star + \@@_typeset_function_basename:N #1 + \bool_if:NT \l_@@_meta_TF_bool { \@@_typeset_TF: } + \@@_typeset_expandability: + \clist_if_empty:NF \l_@@_variants_clist { \@@_typeset_variants: } + \bool_if:NT \g_@@_full_bool { \@@_label_function:N #1 } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_set:Nn \@@_typeset_function_basename:N + { \l_@@_function_name_prefix_tl \cs_to_str:N #1 } +% \end{macrocode} +% +% \begin{macrocode} +\cs_set:Nn \@@_typeset_expandability: + { + & + \bool_if:NT \l_@@_meta_EXP_bool + { + \hspace{\tabcolsep} + \hyperlink{expstar} {$\star$} + } + \bool_if:NT \l_@@_meta_rEXP_bool + { + \hspace{\tabcolsep} + \hyperlink{rexpstar} {\ding{73}} % hollow star } - } -\cs_set:Nn \doc_label_function:N - { - \tl_set:Nx \l_doc_tmpa_tl { \l_doc_function_name_prefix_tl \cs_to_str:N #1 } - \exp_args:NNf \tl_replace_all:Nnn \l_doc_tmpa_tl {\token_to_str:N _} {/} - \exp_args:NNf \tl_remove_all:Nn \l_doc_tmpa_tl {\@backslashchar} - \exp_args:Nx \label {doc/function//\l_doc_tmpa_tl} - } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_set:Nn \@@_typeset_variants: + { + \\ + \@@_typeset_aux:n \g_@@_macro_tl : + \int_compare:nTF { \clist_count:N \l_@@_variants_clist == 1 } + { \exp_after:wN \use_ii:nn \l_@@_variants_clist } + { + \textrm( + \clist_pop:NN \l_@@_variants_clist \l_@@_tmpb_tl + \exp_after:wN \use_ii:nn \l_@@_tmpb_tl + \clist_map_inline:Nn \l_@@_variants_clist {\textrm| \use_ii:nn ##1} + \textrm) + } + \bool_if:NT \l_@@_meta_TF_bool { \@@_typeset_TF: } + & + \bool_if:NT \l_@@_meta_EXP_bool + { + \hspace{\tabcolsep} + \hyperlink{expstar} {$\star$} + } + \bool_if:NT \l_@@_meta_rEXP_bool + { + \hspace{\tabcolsep} + \hyperlink{rexpstar} {\ding{73}} % hollow star + } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_set:Nn \@@_label_function:N + { + \tl_set:Nx \l_@@_tmpa_tl { \l_@@_function_name_prefix_tl \cs_to_str:N #1 } + \exp_args:NNf \tl_replace_all:Nnn \l_@@_tmpa_tl {\token_to_str:N _} {/} + \exp_args:NNf \tl_remove_all:Nn \l_@@_tmpa_tl {\@backslashchar} + \exp_args:Nx \label {doc/function//\l_@@_tmpa_tl} + } % \end{macrocode} % \end{macro} % -% \begin{macro}[aux]{\doc_show_macro_unusual:N} +% \begin{macro}[aux]{\@@_show_macro_unusual:N} % This is for the case when the function is one of the weird ones like \cs{::N}. % \begin{macrocode} -\cs_set_nopar:Nn \doc_show_macro_unusual:N { - \tl_gset:Nx \g_doc_macro_tl { \token_to_str:N #1} +\cs_set_nopar:Nn \@@_show_macro_unusual:N + { + \tl_gset:Nx \g_@@_macro_tl { \token_to_str:N #1} \token_to_str:N #1 & - \exp_args:NNf \tl_replace_all:Nnn \g_doc_macro_tl {\token_to_str:N _} {/} - \exp_args:NNf \tl_replace_all:Nnn \g_doc_macro_tl {\@backslashchar} {} - \bool_if:NT \g_doc_full_bool { - \exp_args:Nx \label { doc/function//\g_doc_macro_tl } - } -} + \exp_args:NNf \tl_replace_all:Nnn \g_@@_macro_tl {\token_to_str:N _} {/} + \exp_args:NNf \tl_replace_all:Nnn \g_@@_macro_tl {\@backslashchar} {} + \bool_if:NT \g_@@_full_bool + { + \exp_args:Nx \label { doc/function//\g_@@_macro_tl } + } + } % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\doc_typeset_dates:} +% \begin{macro}[internal]{\@@_typeset_dates:} % To display metadata for when functions are added/modified. % \begin{macrocode} -\cs_set:Nn \doc_typeset_dates: - { - \bool_if:nF { \tl_if_empty_p:N \l_doc_date_added_tl && - \tl_if_empty_p:N \l_doc_date_updated_tl } - { \midrule } +\cs_set:Nn \@@_typeset_dates: + { + \bool_if:nF { \tl_if_empty_p:N \l_@@_date_added_tl && + \tl_if_empty_p:N \l_@@_date_updated_tl } + { \midrule } - \tl_if_empty:NF \l_doc_date_added_tl - { - \multicolumn{2}{@{}r@{}} - { \scriptsize New:\,\l_doc_date_added_tl } \\ - } + \tl_if_empty:NF \l_@@_date_added_tl + { + \multicolumn{2}{@{}r@{}} + { \scriptsize New:\,\l_@@_date_added_tl } \\ + } - \tl_if_empty:NF \l_doc_date_updated_tl - { - \multicolumn{2}{@{}r@{}} - { \scriptsize Updated:\,\l_doc_date_updated_tl } \\ - } - } + \tl_if_empty:NF \l_@@_date_updated_tl + { + \multicolumn{2}{@{}r@{}} + { \scriptsize Updated:\,\l_@@_date_updated_tl } \\ + } + } % \end{macrocode} % \end{macro} % % \begin{environment}{syntax} % Syntax block placed next to the list of functions to illustrate their use. % \begin{macrocode} -\newenvironment{syntax}{ +\newenvironment{syntax} + { \small\ttfamily - \bool_if:NTF \l_doc_long_name_bool + \bool_if:NTF \l_@@_long_name_bool { - \hcoffin_set:Nw \l_doc_syntax_coffin - \arrayrulecolor{white} - \begin{tabular}{@{}l@{}} - \toprule - \begin{minipage} - { \textwidth+0.75\marginparwidth-\l_doc_trial_width_dim } + \hbox_gset:Nw \g_@@_syntax_box + \arrayrulecolor{white} + \begin{tabular}{@{}l@{}} + \toprule + \begin{minipage} + { \textwidth+0.75\marginparwidth-\l_@@_trial_width_dim } } { - \hcoffin_set:Nw \l_doc_syntax_coffin - \arrayrulecolor{white} - \begin{tabular}{@{}l@{}} - \toprule - \begin{minipage}{ \textwidth } + \hbox_gset:Nw \g_@@_syntax_box + \arrayrulecolor{white} + \begin{tabular}{@{}l@{}} + \toprule + \begin{minipage}{ \textwidth } } \raggedright \obeyspaces\obeylines -}{ + } + { \end{minipage} \end{tabular} \arrayrulecolor{black} - \hcoffin_set_end: - \coffin_gset_eq:NN \l_doc_syntax_coffin \l_doc_syntax_coffin + \hbox_set_end: \ignorespacesafterend -} + } % \end{macrocode} % \end{environment} % -% \begin{macro}{\doc_ensuremath_sb:n} +% \begin{macro}{\@@_ensuremath_sb:n} % \begin{macrocode} -\cs_new:Npn \doc_ensuremath_sb:n #1 - { - \ensuremath{\sb{#1}} - } +\cs_new:Npn \@@_ensuremath_sb:n #1 + { + \ensuremath{\sb{#1}} + } % \end{macrocode} % \end{macro} % -% \begin{macro}{\doc_open_meta:w,\doc_close_meta:n} +% \begin{macro}{\@@_open_meta:w,\@@_close_meta:n} % \begin{macrocode} -\cs_set_eq:NN \doc_meta:n \meta +\cs_set_eq:NN \@@_meta:n \meta \cs_set:Npn \meta - { - \group_begin: - \char_set_active_eq:NN _ \doc_ensuremath_sb:n - \doc_close_meta:n - } -\cs_new:Npn \doc_open_meta:w - { - \group_begin: - \char_set_active_eq:NN _ \doc_ensuremath_sb:n - \doc_close_meta:w - } + { + \group_begin: + \char_set_active_eq:NN _ \@@_ensuremath_sb:n + \@@_close_meta:n + } +\cs_new:Npn \@@_open_meta:w + { + \group_begin: + \char_set_active_eq:NN _ \@@_ensuremath_sb:n + \@@_close_meta:w + } \cs_new:Npn \Arg - { - \texttt{ \char`\{ } - \group_begin: - \char_set_active_eq:NN _ \doc_ensuremath_sb:n - \doc_close_Arg:n - } -\cs_new_nopar:Npn \doc_close_meta:n #1 { \doc_meta:n {#1} \group_end: } -\cs_new_nopar:Npn \doc_close_meta:w #1> { \doc_meta:n {#1} \group_end: } -\cs_new_nopar:Npn \doc_close_Arg:n #1 { - \doc_meta:n {#1} + { + \texttt{ \char`\{ } + \group_begin: + \char_set_active_eq:NN _ \@@_ensuremath_sb:n + \@@_close_Arg:n + } +\cs_new_nopar:Npn \@@_close_meta:n #1 { \@@_meta:n {#1} \group_end: } +\cs_new_nopar:Npn \@@_close_meta:w #1> { \@@_meta:n {#1} \group_end: } +\cs_new_nopar:Npn \@@_close_Arg:n #1 + { + \@@_meta:n {#1} \group_end: \texttt{ \char`\} } -} + } % \end{macrocode} % \end{macro} % @@ -1347,99 +1367,103 @@ Do not distribute a modified version of this file. % Keyval: % \begin{macrocode} \keys_define:nn { l3doc/macro } - { - aux .code:n = - { \bool_set_true:N \l_doc_macro_aux_bool } , - internal .code:n = - { \bool_set_true:N \l_doc_macro_internal_bool } , - var .code:n = - { \bool_set_true:N \l_doc_macro_var_bool } , - TF .code:n = - { \bool_set_true:N \l_doc_macro_TF_bool } , - pTF .code:n = - { \bool_set_true:N \l_doc_macro_pTF_bool } , - tested .code:n = - { } , - } + { + aux .code:n = + { \bool_set_true:N \l_@@_macro_aux_bool } , + internal .code:n = + { \bool_set_true:N \l_@@_macro_internal_bool } , + int .code:n = + { \bool_set_true:N \l_@@_macro_internal_bool } , + var .code:n = + { \bool_set_true:N \l_@@_macro_var_bool } , + TF .code:n = + { \bool_set_true:N \l_@@_macro_TF_bool } , + pTF .code:n = + { \bool_set_true:N \l_@@_macro_pTF_bool } , + tested .code:n = + { } , + EXP .code:n = {} , % TODO + rEXP .code:n = {} , % TODO + added .code:n = {} , % TODO + updated .code:n = {} , % TODO + } % \end{macrocode} % % \begin{macrocode} -\RenewDocumentCommand { \macro } { O{} } { \doc_macro:n {#1} } -\cs_new_protected:Npn \doc_macro:n #1 { +\RenewDocumentCommand { \macro } { O{} } { \@@_macro:n {#1} } +\cs_new_protected:Npn \@@_macro:n #1 + { \int_compare:nNnTF \currentgrouplevel=2 - { \int_gzero:N \g_doc_nested_macro_int } - { \int_incr:N \g_doc_nested_macro_int } + { \int_gzero:N \g_@@_nested_macro_int } + { \int_incr:N \g_@@_nested_macro_int } - \bool_gset_false:N \l_doc_macro_aux_bool - \bool_gset_false:N \l_doc_macro_internal_bool - \bool_gset_false:N \l_doc_macro_TF_bool - \bool_gset_false:N \l_doc_macro_pTF_bool - \bool_gset_false:N \l_doc_macro_var_bool - \bool_gset_false:N \l_doc_tested_bool + \bool_gset_false:N \l_@@_macro_aux_bool + \bool_gset_false:N \l_@@_macro_internal_bool + \bool_gset_false:N \l_@@_macro_TF_bool + \bool_gset_false:N \l_@@_macro_pTF_bool + \bool_gset_false:N \l_@@_macro_var_bool + \bool_gset_false:N \l_@@_tested_bool - \cs_set_eq:NN \doc_macroname_prefix:n \use:n - \cs_set_eq:NN \doc_macroname_suffix: \c_empty_tl + \cs_set_eq:NN \@@_macroname_prefix:n \use:n + \cs_set_eq:NN \@@_macroname_suffix: \c_empty_tl \keys_set:nn { l3doc/macro } {#1} - \cs_set_eq:NN \testfile \doc_print_testfile:n + \cs_set_eq:NN \testfile \@@_print_testfile:n \peek_meaning_ignore_spaces:NTF \c_group_begin_token - { - \group_begin: - \MakePrivateLetters - \char_set_catcode_letter:N \\ - \char_set_catcode_ignore:N \ % space - \char_set_catcode_ignore:N \^^M - \char_set_catcode_ignore:N \^^I - \doc_macro_aux:n - } - { - \doc_macro_verbatim:w - } -} -\NewDocumentCommand {\doc_macro_verbatim:w} {v} - { - \group_begin: % pretty useless - \doc_macro_aux:n {#1} - } -\keys_define:nn { l3doc/macro } - { - unknown .code:n = { \use:c{doc_macro_opt_#1:} } - } + { + \group_begin: + \MakePrivateLetters + \char_set_catcode_letter:N \\ + \char_set_catcode_ignore:N \ % space + \char_set_catcode_ignore:N \^^M + \char_set_catcode_ignore:N \^^I + \@@_macro_aux:n + } + { + \@@_macro_verbatim:w + } + } +\NewDocumentCommand {\@@_macro_verbatim:w} {v} + { + \group_begin: % pretty useless + \@@_macro_aux:n {#1} + } % \end{macrocode} % After changing the catcodes, parse the arguments: % \begin{macrocode} -\clist_new:N \l_doc_macro_input_clist -\cs_new_nopar:Npn \doc_macro_aux:n #1 { +\clist_new:N \l_@@_macro_input_clist +\cs_new_nopar:Npn \@@_macro_aux:n #1 + { \group_end: - \clist_set:Nn \l_doc_macro_input_clist {#1} - \bool_if:NTF \l_doc_macro_pTF_bool - { - \clist_map_inline:Nn \l_doc_macro_input_clist + \clist_set:Nn \l_@@_macro_input_clist {#1} + \bool_if:NTF \l_@@_macro_pTF_bool + { + \clist_map_inline:Nn \l_@@_macro_input_clist { - \exp_args:Nx \doc_macro_single:n { \doc_predicate_from_base:w ##1 \q_nil } + \exp_args:Nx \@@_macro_single:n { \@@_predicate_from_base:w ##1 \q_nil } } - \bool_set_true:N \l_doc_macro_TF_bool - \clist_map_function:NN \l_doc_macro_input_clist \doc_macro_single:n - \bool_set_false:N \l_doc_macro_TF_bool - } - { \clist_map_function:NN \l_doc_macro_input_clist \doc_macro_single:n } -} + \bool_set_true:N \l_@@_macro_TF_bool + \clist_map_function:NN \l_@@_macro_input_clist \@@_macro_single:n + \bool_set_false:N \l_@@_macro_TF_bool + } + { \clist_map_function:NN \l_@@_macro_input_clist \@@_macro_single:n } + } % \end{macrocode} % % \end{environment} % % \begin{macrocode} -\cs_set:Nn \doc_predicate_from_base:N - { - \__cs_get_function_name:N #1 _p: \__cs_get_function_signature:N #1 - } -\cs_set:Npn \doc_predicate_from_base:w #1 : #2 \q_nil - { - #1 _p: #2 - } +\cs_set:Nn \@@_predicate_from_base:N + { + \__cs_get_function_name:N #1 _p: \__cs_get_function_signature:N #1 + } +\cs_set:Npn \@@_predicate_from_base:w #1 : #2 \q_nil + { + #1 _p: #2 + } % \end{macrocode} % % \begin{environment}{doc_macro_single} @@ -1449,15 +1473,17 @@ Do not distribute a modified version of this file. % \begin{arguments} % \item Macro/function/whatever name; input has already been sanitised. % \end{arguments} -% \cs{l_doc_at_replaced_macro_tl} stores the macro name after +% \cs{l_@@_at_replaced_macro_tl} stores the macro name after % replacement of |@@|. % \begin{macrocode} -\tl_new:N \l_doc_at_replaced_macro_tl -\cs_set_nopar:Npn \doc_macro_single:n #1 { - \int_incr:N \l_doc_macro_int - \tl_set:Nx \l_doc_at_replaced_macro_tl { \token_to_str:N #1 } - \doc_replace_at_at:N \l_doc_at_replaced_macro_tl - \tl_set_eq:NN \saved@macroname \l_doc_at_replaced_macro_tl +\cs_set_nopar:Npn \@@_macro_single:n #1 + { + \int_incr:N \l_@@_macro_int + + \tl_set:Nx \l_@@_at_replaced_macro_tl { \token_to_str:N #1 } + \@@_replace_at_at:N \l_@@_at_replaced_macro_tl + \tl_set_eq:NN \saved@macroname \l_@@_at_replaced_macro_tl + \topsep\MacroTopsep \trivlist \cs_set_nopar:Npn \makelabel ##1 { \llap{##1} } @@ -1468,60 +1494,71 @@ Do not distribute a modified version of this file. \cs_set_nopar:Npx \@tempa{\@tempa\hbox{\strut}} \advance\count@\m@ne \repeat - \cs_set_nopar:Npx \makelabel ##1 { + \cs_set_nopar:Npx \makelabel ##1 + { \llap{\vtop to\baselineskip {\@tempa\hbox{##1}\vss}} - } + } \advance \macro@cnt \@ne \else \macro@cnt \@ne \fi - \bool_if:NT \l_doc_macro_aux_bool { - \cs_set_eq:NN \doc_macroname_prefix:n \doc_typeset_aux:n - } - \bool_if:NT \l_doc_macro_TF_bool { - \cs_set_eq:NN \doc_macroname_suffix: \doc_typeset_TF: - } + \bool_if:NT \l_@@_macro_aux_bool + { + \cs_set_eq:NN \@@_macroname_prefix:n \@@_typeset_aux:n + } + \bool_if:NT \l_@@_macro_TF_bool + { + \cs_set_eq:NN \@@_macroname_suffix: \@@_typeset_TF: + } - \bool_if:NF \l_doc_macro_aux_bool { - \tl_gset:Nx \l_doc_macro_tl { \tl_to_str:N \l_doc_at_replaced_macro_tl } - \exp_args:NNf \tl_greplace_all:Nnn \l_doc_macro_tl {\token_to_str:N _} {/} - \exp_args:NNf \tl_greplace_all:Nnn \l_doc_macro_tl {\@backslashchar} {} - } + \bool_if:NF \l_@@_macro_aux_bool + { + \tl_gset:Nx \l_@@_macro_tl { \tl_to_str:N \l_@@_at_replaced_macro_tl } + \exp_args:NNf \tl_greplace_all:Nnn \l_@@_macro_tl {\token_to_str:N _} {/} + \exp_args:NNf \tl_greplace_all:Nnn \l_@@_macro_tl {\@backslashchar} {} + } - \use:x { - \exp_not:N \item [ \exp_not:N \doc_print_macroname:n { - \tl_to_str:N \l_doc_at_replaced_macro_tl + \use:x + { + \exp_not:N \item [ \exp_not:N \@@_print_macroname:n { + \tl_to_str:N \l_@@_at_replaced_macro_tl }] - } - \global\advance \c@CodelineNo \@ne + } + \int_gincr:N \g_@@_codeline_int - \bool_if:NF \l_doc_macro_aux_bool { - \bool_if:NTF \l_doc_macro_TF_bool { - \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_doc_at_replaced_macro_tl \tl_to_str:n {TF} } - \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_doc_at_replaced_macro_tl \tl_to_str:n {T } } - \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_doc_at_replaced_macro_tl \tl_to_str:n { F} } - }{ - \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_doc_at_replaced_macro_tl } - } - } - \bool_if:NTF \l_doc_macro_TF_bool { - \exp_args:Nx \SpecialMainIndex{ \tl_to_str:N \l_doc_at_replaced_macro_tl TF}\nobreak - \exp_args:Nx \DoNotIndex{ \tl_to_str:N \l_doc_at_replaced_macro_tl TF} - }{ - \exp_args:Nx \SpecialMainIndex{ \tl_to_str:N \l_doc_at_replaced_macro_tl }\nobreak - \exp_args:Nx \DoNotIndex{ \tl_to_str:N \l_doc_at_replaced_macro_tl } - } + \bool_if:NF \l_@@_macro_aux_bool + { + \bool_if:NTF \l_@@_macro_TF_bool + { + \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_@@_at_replaced_macro_tl \tl_to_str:n {TF} } + \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_@@_at_replaced_macro_tl \tl_to_str:n {T } } + \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_@@_at_replaced_macro_tl \tl_to_str:n { F} } + } + { + \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_@@_at_replaced_macro_tl } + } + } + \bool_if:NTF \l_@@_macro_TF_bool + { + \exp_args:Nx \SpecialMainIndex{ \tl_to_str:N \l_@@_at_replaced_macro_tl TF}\nobreak + \exp_args:Nx \DoNotIndex{ \tl_to_str:N \l_@@_at_replaced_macro_tl TF} + } + { + \exp_args:Nx \SpecialMainIndex{ \tl_to_str:N \l_@@_at_replaced_macro_tl }\nobreak + \exp_args:Nx \DoNotIndex{ \tl_to_str:N \l_@@_at_replaced_macro_tl } + } - \global\advance \c@CodelineNo \m@ne + \int_gdecr:N \g_@@_codeline_int \ignorespaces -} + } % \end{macrocode} % -% \begin{macro}{\doc_print_macroname:n} +% \begin{macro}{\@@_print_macroname:n} % \begin{macrocode} -\tl_clear:N \l_doc_macro_tl -\cs_set_nopar:Npn \doc_print_macroname:n #1 { +\tl_clear:N \l_@@_macro_tl +\cs_set_nopar:Npn \@@_print_macroname:n #1 + { \strut \HD@target \int_compare:nTF { \tl_count:n {#1} <= 28 } @@ -1529,118 +1566,143 @@ Do not distribute a modified version of this file. % INEFFICIENT: (!) \exp_args:NNx \seq_if_in:NnTF \g_doc_functions_seq - { #1 \bool_if:NT \l_doc_macro_TF_bool { \tl_to_str:n {TF} } } - { - \hyperref [doc/function//\l_doc_macro_tl] - } - { \use:n } - { - \doc_macroname_prefix:n {#1} \doc_macroname_suffix: \ % space! - } -} + { #1 \bool_if:NT \l_@@_macro_TF_bool { \tl_to_str:n {TF} } } + { + \hyperref [doc/function//\l_@@_macro_tl] + } + { \use:n } + { + \@@_macroname_prefix:n {#1} \@@_macroname_suffix: \ % space! + } + } % \end{macrocode} % \end{macro} % \end{environment} % % \begin{macro}{\MacroLongFont} % \begin{macrocode} -\providecommand \MacroLongFont { +\providecommand \MacroLongFont + { \fontfamily{lmtt}\fontseries{lc}\small -} + } % \end{macrocode} % \end{macro} % -% \begin{macro}{\doc_typeset_TF:,\doc_typeset_aux:n} +% \begin{macro}{\@@_typeset_TF:,\@@_typeset_aux:n} % Used by \cs{doc_macro_single} and \cs{doc_showmacro_aux_ii:w} to typeset % conditionals and auxiliary functions. % \begin{macrocode} -\cs_set_nopar:Npn \doc_typeset_TF: { - \hyperlink{explTF}{% - \color{black}% - \itshape TF% - \makebox[0pt][r]{% +\cs_set_nopar:Npn \@@_typeset_TF: + { + \hyperlink{explTF} + { + \color{black} + \itshape TF + \makebox[0pt][r] + { \color{red} \underline { \phantom{\itshape TF} \kern-0.1em } - } - } -} -\cs_set_nopar:Npn \doc_typeset_aux:n #1 { - {\color[gray]{0.7} #1} -} + } + } + } +\cs_set_nopar:Npn \@@_typeset_aux:n #1 + { + { \color[gray]{0.7} #1 } + } % \end{macrocode} % \end{macro} % -% \begin{macro}{\doc_print_testfile:n} +% \begin{macro}{\@@_print_testfile:n} % Used to show that a macro has a test, somewhere. % \begin{macrocode} -\DeclareDocumentCommand \doc_print_testfile:n {m} { - \bool_set_true:N \l_doc_tested_bool - \tl_if_eq:nnF {#1} {*} { - \seq_if_in:NnF \g_doc_testfiles_seq {#1} - { - \par{\footnotesize(\textit{ - The~ test~ suite~ for~ this~ command,~ and~ others~ in~ this~ file,~ is~ \textsf{#1}}. - )\par} - \seq_gput_right:Nn \g_doc_testfiles_seq {#1} - } - } -} +\DeclareDocumentCommand \@@_print_testfile:n {m} + { + \bool_set_true:N \l_@@_tested_bool + \tl_if_eq:nnF {#1} {*} + { + \seq_if_in:NnF \g_@@_testfiles_seq {#1} + { + \seq_gput_right:Nn \g_@@_testfiles_seq {#1} + \par + \@@_print_testfile_aux:n {#1} + } + } + } +% \end{macrocode} +% Text for displaying: +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_testfile_aux:n #1 + { + \footnotesize + ( + \textit{ + The~ test~ suite~ for~ this~ command,~ + and~ others~ in~ this~ file,~ is~ \textsf{#1} + }. + )\par + } % \end{macrocode} % \end{macro} % % \begin{macro}{\TestFiles} % \begin{macrocode} -\DeclareDocumentCommand \TestFiles {m} { +\DeclareDocumentCommand \TestFiles {m} + { \par {\itshape The~ following~ test~ files~ are~ used~ for~ this~ code:~ \textsf{#1}. } \par\ignorespaces -} + } % \end{macrocode} % \end{macro} % % \begin{macro}{\UnitTested} % \begin{macrocode} -\DeclareDocumentCommand \UnitTested {} { - \testfile* -} +\DeclareDocumentCommand \UnitTested {} { \testfile* } % \end{macrocode} % \end{macro} % % \begin{macro}{\TestMissing} -% Note: There \cs{l_doc_macro_input_clist} may contain unconverted |@@|. +% Note: There \cs{l_@@_macro_input_clist} may contain unconverted |@@|. % \begin{macrocode} \cs_generate_variant:Nn \prop_gput:Nnn {NVx} -\DeclareDocumentCommand \TestMissing {m} { - \prop_if_in:NVTF \g_doc_missing_tests_prop \l_doc_macro_input_clist - { - \prop_get:NVN \g_doc_missing_tests_prop \l_doc_macro_input_clist \l_doc_tmpa_tl - \prop_gput:NVx \g_doc_missing_tests_prop \l_doc_macro_input_clist - { - *~ \l_doc_tmpa_tl +\DeclareDocumentCommand \TestMissing {m} + { + \prop_if_in:NVTF \g_@@_missing_tests_prop \l_@@_macro_input_clist + { + \prop_get:NVN \g_@@_missing_tests_prop \l_@@_macro_input_clist \l_@@_tmpa_tl + \prop_gput:NVx \g_@@_missing_tests_prop \l_@@_macro_input_clist + { + *~ \l_@@_tmpa_tl ^^J \exp_not:n {\space\space\space\space\space\space} *~ #1 - } - } - { \prop_gput:NVn \g_doc_missing_tests_prop \l_doc_macro_input_clist {#1} } -} + } + } + { \prop_gput:NVn \g_@@_missing_tests_prop \l_@@_macro_input_clist {#1} } + } % \end{macrocode} % \end{macro} % -% \begin{variable}{\g_doc_module_name_tl} -% \begin{macro}[int]{\doc_replace_at_at:N} +% \begin{variable}{\g_@@_module_name_tl} +% \begin{macro}[internal]{\@@_replace_at_at:N} % \begin{macrocode} -\tl_new:N \g_doc_module_name_tl -\cs_new_protected:Npn \doc_replace_at_at:N #1 { - \tl_if_empty:NF \g_doc_module_name_tl - { - \tl_replace_all:Non #1 { \token_to_str:N @ } { @ } - \tl_replace_all:Non #1 { \token_to_str:N _ } { _ } - \tl_replace_all:Nox #1 { _@@ } { __ \g_doc_module_name_tl } - \tl_replace_all:Nox #1 { @@ } { __ \g_doc_module_name_tl } - } -} +\tl_new:N \g_@@_module_name_tl +\cs_new_protected:Npn \@@_replace_at_at:N #1 + { + \tl_if_empty:NF \g_@@_module_name_tl + { + \tl_replace_all:Non #1 { \token_to_str:N @ } { @ } + \tl_replace_all:Non #1 { \token_to_str:N _ } { _ } +% \end{macrocode} +% To make the search-and-replace work, in the source of l3doc +% itself the \verb|@@| search string needs to be protected from +% replacement by l3docstrip! This is easy to do by adding a space. +% \begin{macrocode} + \tl_replace_all:Nox #1 { _@ @ } { __ \g_@@_module_name_tl } + \tl_replace_all:Nox #1 { @ @ } { __ \g_@@_module_name_tl } + } + } \cs_generate_variant:Nn \tl_replace_all:Nnn { Non, Nox } % \end{macrocode} % \end{macro} @@ -1652,69 +1714,74 @@ Do not distribute a modified version of this file. % go inline in the definition of \cs{endmacro}, but somehow the |#| % doesn't go through some \LaTeXe{} internals. % \begin{macrocode} -\cs_new_protected:Nn \doc_endmacro_build_seq:N - { - \seq_gclear:N #1 - \clist_map_inline:Nn \l_doc_macro_input_clist - { - \tl_set:Nn \l_doc_tmpa_tl {##1} - \doc_replace_at_at:N \l_doc_tmpa_tl - \seq_gput_right:No #1 { \l_doc_tmpa_tl } - } - } -\cs_set_protected:Nn \doc_endmacro_wrap_each:N - { - \bool_if:NTF \l_doc_macro_TF_bool - { \seq_gset_map:NNn #1 #1 { \exp_not:N \texttt { ##1 TF } } } - { \seq_gset_map:NNn #1 #1 { \exp_not:N \texttt { ##1 } } } - } -\cs_set:Nn \doc_texttt_comma:n {\,,~\texttt{#1}} -\cs_set:Npn \endmacro { - \int_compare:nT {\g_doc_nested_macro_int<1} - { - \par\nobreak\noindent{\footnotesize(\emph{ +\cs_new_protected:Nn \@@_endmacro_build_seq:N + { + \seq_gclear:N #1 + \clist_map_inline:Nn \l_@@_macro_input_clist + { + \tl_set:Nn \l_@@_tmpa_tl {##1} + \@@_replace_at_at:N \l_@@_tmpa_tl + \seq_gput_right:No #1 { \l_@@_tmpa_tl } + } + } +\cs_set_protected:Nn \@@_endmacro_wrap_each:N + { + \bool_if:NTF \l_@@_macro_TF_bool + { \seq_gset_map:NNn #1 #1 { \exp_not:N \texttt { ##1 TF } } } + { \seq_gset_map:NNn #1 #1 { \exp_not:N \texttt { ##1 } } } + } +\cs_set:Nn \@@_texttt_comma:n {\,,~\texttt{#1}} +\cs_set:Npn \endmacro + { + \int_compare:nT { \g_@@_nested_macro_int < 1 } + { + \par\nobreak\noindent{\footnotesize(\emph{ End~ definition~ for~ - \doc_endmacro_build_seq:N \g_doc_tmpa_seq - \doc_endmacro_wrap_each:N \g_doc_tmpa_seq - \int_compare:nTF { \seq_count:N \g_doc_tmpa_seq <= 3 } + \@@_endmacro_build_seq:N \g_@@_tmpa_seq + \@@_endmacro_wrap_each:N \g_@@_tmpa_seq + \int_compare:nTF { \seq_count:N \g_@@_tmpa_seq <= 3 } { - \seq_use:Nnnn \g_doc_tmpa_seq + \seq_use:Nnnn \g_@@_tmpa_seq { \,~and~ } { \,,~ } { \,,~and~ } } - { \seq_item:Nn \g_doc_tmpa_seq {1}\,~and~others. } - \bool_if:nT { - !\l_doc_macro_aux_bool && - !\l_doc_macro_internal_bool && - \int_compare_p:n {\g_doc_nested_macro_int<1} - } - { - \int_compare:nNnTF \l_doc_macro_int=1 {~This~} {~These~} - \bool_if:NTF \l_doc_macro_var_bool{variable}{function} - \int_compare:nNnTF \l_doc_macro_int=1 {~is~}{s~are~} - documented~on~page~ - \exp_args:Nx\pageref{doc/function//\l_doc_macro_tl}. - } - })\par} - } + { \seq_item:Nn \g_@@_tmpa_seq {1}\,~and~others. } + + \bool_if:nT + { + !\l_@@_macro_aux_bool && + !\l_@@_macro_internal_bool && + \int_compare_p:n {\g_@@_nested_macro_int<1} + } + { + \int_compare:nNnTF \l_@@_macro_int=1 {~This~} {~These~} + \bool_if:NTF \l_@@_macro_var_bool{variable}{function} + \int_compare:nNnTF \l_@@_macro_int=1 {~is~}{s~are~} + documented~on~page~ + \exp_args:Nx\pageref{doc/function//\l_@@_macro_tl}. + } + })\par} + } + \bool_if:nT - { \g_doc_checktest_bool && - !( \l_doc_macro_aux_bool || \l_doc_macro_var_bool ) && - !\l_doc_tested_bool - } - { - \seq_gput_right:Nx \g_doc_not_tested_seq - { - \seq_use:Nnnn \g_doc_tmpa_seq { , } { , } { , } - \bool_if:NT \l_doc_macro_pTF_bool {~(pTF)} - \bool_if:NT \l_doc_macro_TF_bool {~(TF)} - } - } -} + { + \g_@@_checktest_bool && + !( \l_@@_macro_aux_bool || \l_@@_macro_var_bool ) && + !\l_@@_tested_bool + } + { + \seq_gput_right:Nx \g_@@_not_tested_seq + { + \seq_use:Nnnn \g_@@_tmpa_seq { , } { , } { , } + \bool_if:NT \l_@@_macro_pTF_bool {~(pTF)} + \bool_if:NT \l_@@_macro_TF_bool {~(TF)} + } + } + } % \end{macrocode} % \end{macro} % % \begin{environment}{macrocode} -% \begin{macro}[aux]{\doc_xmacro_code:n} +% \begin{macro}[aux]{\@@_xmacro_code:n} % Hook into the \texttt{macrocode} environment in a dirty way: % \cs{xmacro@code} is responsible for grabbing (and tokenizing) the % body of the environment. Redefine it to pass what it grabs to @@ -1739,39 +1806,39 @@ Do not distribute a modified version of this file. \char_set_lccode:nn { `\^^L } { `\{ } \char_set_lccode:nn { `\^^R } { `\} } \tl_to_lowercase:n - { - \group_end: - \cs_set_protected:Npn \xmacro@code - #1 ^^A ^^S^^S^^S^^S ^^Bend ^^Lmacrocode^^R - { \doc_xmacro_code:n {#1} /end{macrocode} } - } + { + \group_end: + \cs_set_protected:Npn \xmacro@code + #1 ^^A ^^S^^S^^S^^S ^^Bend ^^Lmacrocode^^R + { \@@_xmacro_code:n {#1} /end{macrocode} } + } \group_begin: \char_set_catcode_active:N \< \char_set_catcode_active:N \> - \cs_new_protected:Npn \doc_xmacro_code:n #1 - { - \tl_if_in:nnTF {#1} { < @ @ = } - { \doc_xmacro_code:w #1 \q_stop } - { - \tl_set:Nn \l_doc_tmpa_tl {#1} - \doc_replace_at_at:N \l_doc_tmpa_tl - \tl_use:N \l_doc_tmpa_tl - } - } - \cs_new_protected:Npn \doc_xmacro_code:w #1 < @ @ = #2 > #3 \q_stop - { - \tl_set:Nn \l_doc_tmpa_tl {#1} - \doc_replace_at_at:N \l_doc_tmpa_tl + \cs_new_protected:Npn \@@_xmacro_code:n #1 + { + \tl_if_in:nnTF {#1} { < @ @ = } + { \@@_xmacro_code:w #1 \q_stop } + { + \tl_set:Nn \l_@@_tmpa_tl {#1} + \@@_replace_at_at:N \l_@@_tmpa_tl + \tl_use:N \l_@@_tmpa_tl + } + } + \cs_new_protected:Npn \@@_xmacro_code:w #1 < @ @ = #2 > #3 \q_stop + { + \tl_set:Nn \l_@@_tmpa_tl {#1} + \@@_replace_at_at:N \l_@@_tmpa_tl - \tl_gset:Nn \g_doc_module_name_tl {#2} - \tl_put_right:Nn \l_doc_tmpa_tl { < @ @ = #2 > } + \tl_gset:Nn \g_@@_module_name_tl {#2} + \tl_put_right:Nn \l_@@_tmpa_tl { < @ @ = #2 > } - \tl_set:Nn \l_doc_tmpb_tl {#3} - \doc_replace_at_at:N \l_doc_tmpb_tl - \tl_put_right:No \l_doc_tmpa_tl { \l_doc_tmpb_tl } + \tl_set:Nn \l_@@_tmpb_tl {#3} + \@@_replace_at_at:N \l_@@_tmpb_tl + \tl_put_right:No \l_@@_tmpa_tl { \l_@@_tmpb_tl } - \tl_use:N \l_doc_tmpa_tl - } + \tl_use:N \l_@@_tmpa_tl + } \group_end: % \end{macrocode} % \end{macro} @@ -1781,42 +1848,54 @@ Do not distribute a modified version of this file. % For describing package options. Due to Joseph Wright. % Name/usage might change soon. % \begin{macrocode} -\newcommand*{\DescribeOption}{ - \leavevmode - \@bsphack - \begingroup - \MakePrivateLetters - \Describe@Option -} -\newcommand*{\Describe@Option}[1]{ - \endgroup - \marginpar{ - \raggedleft - \PrintDescribeEnv{#1} - } - \SpecialOptionIndex{#1} - \@esphack - \ignorespaces -} -\newcommand*{\SpecialOptionIndex}[1]{ - \@bsphack - \begingroup - \HD@target - \let\HDorg@encapchar\encapchar - \edef\encapchar usage{ - \HDorg@encapchar hdclindex{\the\c@HD@hypercount}{usage} - } - \index{ - #1\actualchar{\protect\ttfamily#1}~(option) - \encapchar usage - } - \index{ - options:\levelchar#1\actualchar{\protect\ttfamily#1} - \encapchar usage - } - \endgroup - \@esphack -} +\newcommand*{\DescribeOption} + { + \leavevmode + \@bsphack + \begingroup + \MakePrivateLetters + \Describe@Option + } +% \end{macrocode} +% +% \begin{macrocode} +\newcommand*{\Describe@Option}[1] + { + \endgroup + \marginpar{ + \raggedleft + \PrintDescribeEnv{#1} + } + \SpecialOptionIndex{#1} + \@esphack + \ignorespaces + } +% \end{macrocode} +% +% \begin{macrocode} +\newcommand*{\SpecialOptionIndex}[1] + { + \@bsphack + \begingroup + \HD@target + \let\HDorg@encapchar\encapchar + \edef\encapchar usage + { + \HDorg@encapchar hdclindex{\the\c@HD@hypercount}{usage} + } + \index + { + #1\actualchar{\protect\ttfamily#1}~(option) + \encapchar usage + } + \index + { + options:\levelchar#1\actualchar{\protect\ttfamily#1} + \encapchar usage + } + \endgroup + \@esphack + } % \end{macrocode} % \end{macro} % @@ -1844,14 +1923,16 @@ Do not distribute a modified version of this file. % package that might be tricky to use. % FIXME: Has to be fixed when in combination with a macro-definition. % \begin{macrocode} -\newenvironment {danger} { +\newenvironment {danger} + { \begin{trivlist}\item[]\noindent \begingroup\hangindent=2pc\hangafter=-2 \cs_set_nopar:Npn \par{\endgraf\endgroup} \hbox to0pt{\hskip-\hangindent\dbend\hfill}\ignorespaces -}{ + } + { \par\end{trivlist} -} + } % \end{macrocode} % % \begin{ddanger} @@ -1860,14 +1941,15 @@ Do not distribute a modified version of this file. % about such things. % \end{ddanger} % \begin{macrocode} -\newenvironment {ddanger} { +\newenvironment {ddanger} + { \begin{trivlist}\item[]\noindent \begingroup\hangindent=3.5pc\hangafter=-2 \cs_set_nopar:Npn \par{\endgraf\endgroup} \hbox to0pt{\hskip-\hangindent\dbend\kern2pt\dbend\hfill}\ignorespaces -}{ + }{ \par\end{trivlist} -} + } % \end{macrocode} % \end{environment} % \end{environment} @@ -1876,47 +1958,61 @@ Do not distribute a modified version of this file. % % \begin{macrocode} \newenvironment{TemplateInterfaceDescription}[1] - {\subsection{The~object~type~`#1'}% - \begingroup - \@beginparpenalty\@M - \description - \def\TemplateArgument##1##2{\item[Arg:~##1]##2\par}% - \def\TemplateSemantics{\enddescription\endgroup - \subsubsection*{Semantics:}}% - } - {\par\bigskip} + { + \subsection{The~object~type~`#1'} + \begingroup + \@beginparpenalty\@M + \description + \def\TemplateArgument##1##2{\item[Arg:~##1]##2\par} + \def\TemplateSemantics + { + \enddescription\endgroup + \subsubsection*{Semantics:} + } + } + { + \par\bigskip + } % \end{macrocode} % % \begin{macrocode} \newenvironment{TemplateDescription}[2] - {\subsection{The~template~`#2'~(object~type~#1)}% - \subsubsection*{Attributes:}% + { + \subsection{The~template~`#2'~(object~type~#1)} + \subsubsection*{Attributes:} \begingroup \@beginparpenalty\@M \description - \def\TemplateKey##1##2##3##4{\item[##1~(##2)]##3% + \def\TemplateKey##1##2##3##4 + { + \item[##1~(##2)]##3% \ifx\TemplateKey##4\TemplateKey\else % \hskip0ptplus3em\penalty-500\hskip 0pt plus 1filll Default:~##4% \hfill\penalty500\hbox{}\hfill Default:~##4% \nobreak\hskip-\parfillskip\hskip0pt\relax \fi - \par}% - \def\TemplateSemantics{\enddescription\endgroup - \subsubsection*{Semantics~\&~Comments:}}% + \par + } + \def\TemplateSemantics + { + \enddescription\endgroup + \subsubsection*{Semantics~\&~Comments:} + } } {\par\bigskip} % \end{macrocode} % % \begin{macrocode} \newenvironment{InstanceDescription}[4][xxxxxxxxxxxxxxx] - {\subsubsection{The~instance~`#3'~(template~#2/#4)}% - \subsubsection*{Attribute~values:}% + { + \subsubsection{The~instance~`#3'~(template~#2/#4)} + \subsubsection*{Attribute~values:} \begingroup \@beginparpenalty\@M - \def\InstanceKey##1##2{\>\textbf{##1}\>##2\\}% + \def\InstanceKey##1##2{\>\textbf{##1}\>##2\\} \def\InstanceSemantics{\endtabbing\endgroup \vskip-30pt\vskip0pt - \subsubsection*{Layout~description~\&~Comments:}}% + \subsubsection*{Layout~description~\&~Comments:}} \tabbing xxxx\=#1\=\kill } @@ -1930,22 +2026,25 @@ Do not distribute a modified version of this file. % % \begin{macro}{\StopEventually,\Finale,\AlsoImplementation,\OnlyDescription} % \begin{macrocode} -\cs_set_nopar:Npn \AlsoImplementation { - \bool_set_true:N \g_doc_implementation_bool - \cs_set:Npn \StopEventually ##1 { +\cs_set_nopar:Npn \AlsoImplementation + { + \bool_set_true:N \g_@@_implementation_bool + \cs_set:Npn \StopEventually ##1 + { \@bsphack \cs_gset_nopar:Npn \Finale { ##1 \check@checksum } \init@checksum \@esphack - } -} + } + } \AlsoImplementation -\cs_set_nopar:Npn \OnlyDescription { +\cs_set_nopar:Npn \OnlyDescription + { \@bsphack - \bool_set_false:N \g_doc_implementation_bool + \bool_set_false:N \g_@@_implementation_bool \cs_set:Npn \StopEventually ##1 { ##1 \endinput } \@esphack -} + } \cs_set_eq:NN \Finale \relax % \end{macrocode} % \end{macro} @@ -1957,14 +2056,16 @@ Do not distribute a modified version of this file. % \begin{macro}{\DocInput} % From \pkg{doc}. Now accepts comma-list input (who has commas in filenames?). % \begin{macrocode} -\cs_set:Npn \DocInput #1 { - \clist_map_inline:nn {#1} { +\cs_set:Npn \DocInput #1 + { + \clist_map_inline:nn {#1} + { \clist_put_right:Nn \g_docinput_clist {##1} \MakePercentIgnore \input{##1} \MakePercentComment - } -} + } + } % \end{macrocode} % \end{macro} % @@ -1972,13 +2073,15 @@ Do not distribute a modified version of this file. % Uses "\g_docinput_clist" to re-input whatever's already been "\DocInput"-ed until now. % May be used multiple times. % \begin{macrocode} -\cs_set:Npn \DocInputAgain { - \clist_map_inline:Nn \g_docinput_clist { +\cs_set:Npn \DocInputAgain + { + \clist_map_inline:Nn \g_docinput_clist + { \MakePercentIgnore \input{##1} \MakePercentComment - } -} + } + } % \end{macrocode} % \end{macro} % @@ -1990,33 +2093,34 @@ Do not distribute a modified version of this file. % \end{macrocode} % % \begin{macrocode} -\newcommand*{\DocInclude}[1]{% +\newcommand*{\DocInclude}[1] + { \relax\clearpage \docincludeaux - \IfFileExists{#1.fdd}{ - \cs_set_nopar:Npn \currentfile{#1.fdd} - }{ - \cs_set_nopar:Npn \currentfile{#1.dtx} - } + \IfFileExists{#1.fdd} + { \cs_set_nopar:Npn \currentfile{#1.fdd} } + { \cs_set_nopar:Npn \currentfile{#1.dtx} } \ifnum\@auxout=\@partaux \@latexerr{\string\include\space cannot~be~nested}\@eha \else \@docinclude #1 \fi -} + } % \end{macrocode} % % \begin{macrocode} -\cs_set_nopar:Npn \@docinclude #1 { +\cs_set_nopar:Npn \@docinclude #1 + { \clearpage \immediate\write\@mainaux{\string\@input{#1.aux}} \@tempswatrue \if@partsw \@tempswafalse \cs_set_nopar:Npx \@tempb{#1} - \@for\@tempa:=\@partlist\do{ + \@for\@tempa:=\@partlist\do + { \ifx\@tempa\@tempb\@tempswatrue\fi - } + } \fi \if@tempswa \cs_set_eq:NN \@auxout\@partaux @@ -2045,16 +2149,18 @@ Do not distribute a modified version of this file. \@nameuse{cp@#1} \fi \cs_set_eq:NN \@auxout\@mainaux -} + } % \end{macrocode} % % \begin{macrocode} -\cs_gset_nopar:Npn \codeline@wrindex #1 { - \immediate\write\@indexfile { +\cs_gset_nopar:Npn \codeline@wrindex #1 + { + \immediate\write\@indexfile + { \string\indexentry{#1} - {\filesep\number\c@CodelineNo} - } -} + { \filesep \int_use:N \g_@@_codeline_int } + } + } % \end{macrocode} % \end{macro} % @@ -2064,21 +2170,26 @@ Do not distribute a modified version of this file. % % \begin{macro}{\docincludeaux} % \begin{macrocode} -\cs_set_nopar:Npn \docincludeaux { +\cs_set_nopar:Npn \docincludeaux + { \cs_set_nopar:Npn \thepart {\alphalph{part}} \cs_set_nopar:Npn \filesep {\thepart-} \cs_set_eq:NN \filekey\@gobble - \g@addto@macro\index@prologue{ - \cs_gset_nopar:Npn\@oddfoot{ - \parbox{\textwidth}{ + \g@addto@macro\index@prologue + { + \cs_gset_nopar:Npn\@oddfoot + { + \parbox{\textwidth} + { \strut\footnotesize \raggedright{\bfseries File~Key:}~\filekey - } - } + } + } \cs_set_eq:NN \@evenfoot\@oddfoot - } + } \cs_gset_eq:NN \docincludeaux\relax - \cs_gset_nopar:Npn\@oddfoot{ + \cs_gset_nopar:Npn\@oddfoot + { \expandafter\ifx\csname ver@\currentfile\endcsname\relax File~\thepart :~{\ttfamily\currentfile}~ \else @@ -2088,9 +2199,9 @@ Do not distribute a modified version of this file. Version~\ExplFileVersion \fi \hfill\thepage - } + } \cs_set_eq:NN \@evenfoot \@oddfoot -} + } % \end{macrocode} % \end{macro} % @@ -2099,106 +2210,120 @@ Do not distribute a modified version of this file. % Print all defined and documented macros/functions. % % \begin{macrocode} -\iow_new:N \g_doc_func_iow +\iow_new:N \g_@@_func_iow % \end{macrocode} % % \begin{macrocode} -\cs_new_nopar:Npn \doc_show_functions_defined: { - \bool_if:nT { \g_doc_implementation_bool && \g_doc_checkfunc_bool } { +\cs_new_nopar:Npn \@@_show_functions_defined: + { + \bool_if:nT { \g_@@_implementation_bool && \g_@@_checkfunc_bool } + { \typeout{ ======================================== ^^J } - \iow_open:Nn \g_doc_func_iow { \c_job_name_tl .cmds } + \iow_open:Nn \g_@@_func_iow { \c_job_name_tl .cmds } - \tl_clear:N \l_doc_tmpa_tl - \seq_map_inline:Nn \g_doc_functions_seq { - \seq_if_in:NnT \g_doc_macros_seq {##1} { - \tl_put_right:Nn \l_doc_tmpa_tl { ##1 ^^J } - \iow_now:Nn \g_doc_func_iow { > ~ ##1 } - } - } + \tl_clear:N \l_@@_tmpa_tl + \seq_map_inline:Nn \g_doc_functions_seq + { + \seq_if_in:NnT \g_doc_macros_seq {##1} + { + \tl_put_right:Nn \l_@@_tmpa_tl { ##1 ^^J } + \iow_now:Nn \g_@@_func_iow { > ~ ##1 } + } + } - \doc_functions_typeout:n { - Functions~both~documented~and~defined:^^J (In~order~of~being~documented) - } + \@@_functions_typeout:n + { + Functions~both~documented~and~defined:^^J + (In~order~of~being~documented) + } - \seq_map_inline:Nn \g_doc_functions_seq { - \seq_if_in:NnF \g_doc_macros_seq {##1} { - \tl_put_right:Nn \l_doc_tmpa_tl { ##1 ^^J } - \iow_now:Nn \g_doc_func_iow { ! ~ ##1} - } - } - \doc_functions_typeout:n { Functions~documented~but~not~defined: } + \seq_map_inline:Nn \g_doc_functions_seq + { + \seq_if_in:NnF \g_doc_macros_seq {##1} + { + \tl_put_right:Nn \l_@@_tmpa_tl { ##1 ^^J } + \iow_now:Nn \g_@@_func_iow { ! ~ ##1} + } + } + \@@_functions_typeout:n { Functions~documented~but~not~defined: } - \seq_map_inline:Nn \g_doc_macros_seq { - \seq_if_in:NnF \g_doc_functions_seq {##1} { - \tl_put_right:Nn \l_doc_tmpa_tl { ##1 ^^J } - \iow_now:Nn \g_doc_func_iow { ? ~ ##1} - } - } - \doc_functions_typeout:n { Functions~defined~but~not~documented: } + \seq_map_inline:Nn \g_doc_macros_seq + { + \seq_if_in:NnF \g_doc_functions_seq {##1} + { + \tl_put_right:Nn \l_@@_tmpa_tl { ##1 ^^J } + \iow_now:Nn \g_@@_func_iow { ? ~ ##1} + } + } + \@@_functions_typeout:n { Functions~defined~but~not~documented: } - \iow_close:N \g_doc_func_iow + \iow_close:N \g_@@_func_iow \typeout{ ======================================== } } } -\AtEndDocument{ \doc_show_functions_defined: } +\AtEndDocument{ \@@_show_functions_defined: } % \end{macrocode} % % \begin{macrocode} -\cs_set_nopar:Npn \doc_functions_typeout:n #1 { - \tl_if_empty:NF \l_doc_tmpa_tl { - \typeout{ +\cs_set_nopar:Npn \@@_functions_typeout:n #1 + { + \tl_if_empty:NF \l_@@_tmpa_tl + { + \typeout + { -------------------------------------- ^^J #1 ^^J - -------------------------------------- ^^J \l_doc_tmpa_tl - } - \tl_clear:N \l_doc_tmpa_tl - } -} + -------------------------------------- ^^J \l_@@_tmpa_tl + } + \tl_clear:N \l_@@_tmpa_tl + } + } % \end{macrocode} % % \begin{macrocode} -\cs_new:Npn \doc_show_not_tested: { - \bool_if:NT \g_doc_checktest_bool - { - \bool_if:nT { !(\seq_if_empty_p:N \g_doc_not_tested_seq) || - !(\prop_if_empty_p:N \g_doc_missing_tests_prop) } - { - \tl_clear:N \l_doc_tmpa_tl - \prop_if_empty:NF \g_doc_missing_tests_prop - { - \tl_put_right:Nn \l_doc_tmpa_tl - { +\cs_new:Npn \@@_show_not_tested: + { + \bool_if:NT \g_@@_checktest_bool + { + \bool_if:nT { !(\seq_if_empty_p:N \g_@@_not_tested_seq) || + !(\prop_if_empty_p:N \g_@@_missing_tests_prop) } + { + \tl_clear:N \l_@@_tmpa_tl + \prop_if_empty:NF \g_@@_missing_tests_prop + { + \tl_put_right:Nn \l_@@_tmpa_tl + { ^^J^^JThe~ following~ macro(s)~ have~ incomplete~ tests:^^J - } - \prop_map_inline:Nn \g_doc_missing_tests_prop - { - \tl_put_right:Nn \l_doc_tmpa_tl + } + \prop_map_inline:Nn \g_@@_missing_tests_prop + { + \tl_put_right:Nn \l_@@_tmpa_tl {^^J\space\space\space\space ##1 ^^J\space\space\space\space\space\space ##2} - } - } - \seq_if_empty:NF \g_doc_not_tested_seq - { - \tl_put_right:Nn \l_doc_tmpa_tl - { + } + } + \seq_if_empty:NF \g_@@_not_tested_seq + { + \tl_put_right:Nn \l_@@_tmpa_tl + { ^^J^^J The~ following~ macro(s)~ do~ not~ have~ any~ tests:^^J - } - \seq_map_inline:Nn \g_doc_not_tested_seq - { + } + \seq_map_inline:Nn \g_@@_not_tested_seq + { \clist_map_inline:nn {##1} - { - \tl_put_right:Nn \l_doc_tmpa_tl {^^J\space\space\space\space ####1} - } - } + { + \tl_put_right:Nn \l_@@_tmpa_tl {^^J\space\space\space\space ####1} + } + } \int_set:Nn \l_tmpa_int {\etex_interactionmode:D} \errorstopmode - \ClassError{l3doc}{\l_doc_tmpa_tl}{} + \ClassError{l3doc}{\l_@@_tmpa_tl}{} \int_set:Nn \etex_interactionmode:D {\l_tmpa_int} - } - } - } -} -\AtEndDocument{ \doc_show_not_tested: } + } + } + } + } +\AtEndDocument{ \@@_show_not_tested: } % \end{macrocode} % % \subsection{Indexing} @@ -2215,7 +2340,8 @@ Do not distribute a modified version of this file. % % Set up the Index to use "\part" % \begin{macrocode} -\IndexPrologue{ +\IndexPrologue + { \part*{Index} \markboth{Index}{Index} \addcontentsline{toc}{part}{Index} @@ -2223,34 +2349,36 @@ Do not distribute a modified version of this file. corresponding~entry~is~described,~ numbers~underlined~point~to~the~definition,~ all~others~indicate~the~places~where~it~is~used. -} + } % \end{macrocode} % % -% \begin{macro}{\doc_special_main_index:n,\doc_special_main_index:o, \doc_special_main_index:x} +% \begin{macro}{\@@_special_main_index:n,\@@_special_main_index:o, \@@_special_main_index:x} % Heiko's replacement to play nicely with |hypdoc|: % \begin{macrocode} -\cs_set_nopar:Npn \doc_special_main_index:n #1 { +\cs_set_nopar:Npn \@@_special_main_index:n #1 + { \HD@target - \index{ + \index + { \@gobble#1 \actualchar \string\verb\quotechar*\verbatimchar#1\verbatimchar \encapchar hdclindex{\the\c@HD@hypercount}{usage} - } -} -\cs_generate_variant:Nn \doc_special_main_index:n { o , x } + } + } +\cs_generate_variant:Nn \@@_special_main_index:n { o , x } % \end{macrocode} % \end{macro} % % \begin{macrocode} \msg_new:nnn {l3doc} {print-index-howto} - { - Generate~the~index~by~executing\\ - \iow_indent:n { makeindex~-s~l3doc.ist~-o~\c_job_name_tl .ind~\c_job_name_tl .idx } - } + { + Generate~the~index~by~executing\\ + \iow_indent:n { makeindex~-s~l3doc.ist~-o~\c_job_name_tl .ind~\c_job_name_tl .idx } + } \tl_gput_right:Nn \PrintIndex { \AtEndDocument{ \msg_info:nn {l3doc} {print-index-howto} } } % \end{macrocode} % @@ -2259,20 +2387,21 @@ Do not distribute a modified version of this file. % Set the change history to use "\part". % Allow control names to be hyphenated in here... % \begin{macrocode} -\GlossaryPrologue{ +\GlossaryPrologue + { \part*{Change~History} {\GlossaryParms\ttfamily\hyphenchar\font=`\-} \markboth{Change~History}{Change~History} \addcontentsline{toc}{part}{Change~History} -} + } % \end{macrocode} % % \begin{macrocode} \msg_new:nnn {l3doc} {print-changes-howto} - { - Generate~the~change~list~by~executing\\ - \iow_indent:n { makeindex~-s~gglo.ist~-o~\c_job_name_tl .gls~\c_job_name_tl .glo } - } + { + Generate~the~change~list~by~executing\\ + \iow_indent:n { makeindex~-s~gglo.ist~-o~\c_job_name_tl .gls~\c_job_name_tl .glo } + } \tl_gput_right:Nn \PrintChanges { \AtEndDocument{ \msg_info:nn {l3doc} {print-changes-howto} } } % \end{macrocode} % @@ -2299,16 +2428,18 @@ Do not distribute a modified version of this file. % \subsection{Default configuration} % % \begin{macrocode} -\bool_if:NTF \g_doc_full_bool { +\bool_if:NTF \g_@@_full_bool + { \RecordChanges \CodelineIndex \EnableCrossrefs \AlsoImplementation -}{ + } + { \CodelineNumbered \DisableCrossrefs \OnlyDescription -} + } % \end{macrocode} % % @@ -2329,26 +2460,37 @@ Do not distribute a modified version of this file. % % The Guilty Parties. % \begin{macrocode} -\cs_new_nopar:Npn\Team{% - The~\LaTeX3~Project\thanks{% - Frank~Mittelbach,~Denys~Duchier,~Chris~Rowley,~ - Rainer~Sch\"opf,~Johannes~Braams,~Michael~Downes,~ - David~Carlisle,~Alan~Jeffrey,~Morten~H\o{}gholm,~Thomas~Lotze,~ - Javier~Bezos,~Will~Robertson,~Joseph~Wright,~Bruno~Le~Floch}} +\tl_new:N \Team +\tl_set:Nn \Team + { + The~\LaTeX3~Project\thanks + { + Frank~Mittelbach,~Denys~Duchier,~Chris~Rowley,~ + Rainer~Sch\"opf,~Johannes~Braams,~Michael~Downes,~ + David~Carlisle,~Alan~Jeffrey,~Morten~H\o{}gholm,~Thomas~Lotze,~ + Javier~Bezos,~Will~Robertson,~Joseph~Wright,~Bruno~Le~Floch + } + } % \end{macrocode} % % \begin{macrocode} \NewDocumentCommand{\ExplMakeTitle}{mm} { - \title + \title + { + The~\pkg{#1}~package \\ #2 + \thanks { - The~\pkg{#1}~package \\ #2 - \thanks{This~file~describes~v\ExplFileVersion,~ - last~revised~\ExplFileDate.} + This~file~describes~v\ExplFileVersion,~ + last~revised~\ExplFileDate. } - \author{The~\LaTeX3~Project\thanks{E-mail:~ + } + \author + { + The~\LaTeX3~Project\thanks{E-mail:~ \href{mailto:latex-l@listserv.uni-heidelberg.de} - {latex-l@listserv.uni-heidelberg.de}}} + {latex-l@listserv.uni-heidelberg.de}} + } \date{Released~\ExplFileDate} \maketitle } @@ -2369,14 +2511,14 @@ Do not distribute a modified version of this file. % % \begin{macrocode} \AtBeginDocument - { - \clist_map_inline:nn - { - asin, acos, atan, acot, - asinh, acosh, atanh, acoth, round, floor, ceil - } - { \exp_args:Nc \DeclareMathOperator{#1}{#1} } - } + { + \clist_map_inline:nn + { + asin, acos, atan, acot, + asinh, acosh, atanh, acoth, round, floor, ceil + } + { \exp_args:Nc \DeclareMathOperator{#1}{#1} } + } % \end{macrocode} % % \begin{macro}{\nan} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx index 5e2ba0a5e63..623ae7c4fa9 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx @@ -274,4 +274,4 @@ % % \end{implementation} % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx index 817a616897f..b088943d88c 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx @@ -35,8 +35,8 @@ %% % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3drivers.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3drivers.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Experimental drivers} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx index 8e14807cfcf..5c853a3a321 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3expan.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3expan.dtx 4073 2012-08-10 01:33:13Z bruno $ {L3 Argument expansion} %</driver|package> %<*driver> @@ -103,7 +103,7 @@ % how the variants are defined. They just expand into the appropriate % |\exp_| function followed by the desired base function, \emph{e.g.} % \begin{quote} -% |\cs_new_nopar:Npn\seq_gpush:No{\exp_args:NNo\seq_gpush:Nn}| +% |\cs_new_nopar:Npn \seq_gpush:No { \exp_args:NNo \seq_gpush:Nn }| % \end{quote} % Providing variants in this way in style files is uncritical as the % \cs{cs_new_nopar:Npn} function will silently accept definitions whenever the @@ -200,7 +200,7 @@ % \meta{tl~var}. In this example we assume |\l_tmpa_tl| contains % the text string |lur|. The straightforward approach is % \begin{quote} -% |\tl_set:No \l_tmpb_tl {\cs_set_eq:Nc \aaa { b \l_tmpa_tl b } }| +% |\tl_set:No \l_tmpb_tl { \cs_set_eq:Nc \aaa { b \l_tmpa_tl b } }| % \end{quote} % Unfortunately this only puts % |\exp_args:NNc \cs_set_eq:NN \aaa {b \l_tmpa_tl b}| into |\l_tmpb_tl| @@ -208,7 +208,7 @@ % \cs{tl_set:Nx} is not an option as that will die horribly. Instead % we can do a % \begin{quote} -% |\tl_set:Nf \l_tmpb_tl {\cs_set_eq:Nc \aaa { b \l_tmpa_tl b } }| +% |\tl_set:Nf \l_tmpb_tl { \cs_set_eq:Nc \aaa { b \l_tmpa_tl b } }| % \end{quote} % which puts the desired result in |\l_tmpb_tl|. It requires % \cs{tl_set:Nf} to be defined as @@ -443,7 +443,7 @@ % } % \begin{syntax} % \cs{exp_last_unbraced:Nno} \meta{token} \meta{tokens_1} \meta{tokens_2} -% \end{syntax} +% \end{syntax} % These functions absorb the number of arguments given by their % specification, carry out the expansion % indicated and leave the the results in the input stream, with the @@ -462,7 +462,7 @@ % \begin{function}{\exp_last_unbraced:Nx} % \begin{syntax} % \cs{exp_last_unbraced:Nx} \meta{function} \Arg{tokens} -% \end{syntax} +% \end{syntax} % This functions fully expands the \meta{tokens} and leaves % the result in the input stream after reinsertion of \meta{function}. % This function is not expandable. @@ -616,7 +616,7 @@ % \begin{macrocode} %<*initex|package> % \end{macrocode} -% +% % \begin{macrocode} %<@@=exp> % \end{macrocode} @@ -656,11 +656,9 @@ % method for efficiency, typically using calls to \cs{exp_after:wN}. % % \begin{variable}{\l_@@_internal_tl} -% We need a scratch token list variable. -% We don't use |tl| methods so that \pkg{l3expan} can be loaded earlier. -% \begin{macrocode} -\cs_new_nopar:Npn \l_@@_internal_tl { } -% \end{macrocode} +% This scratch token list variable is defined in \pkg{l3basics}, as it +% is needed \enquote{early}. This is just a reminder that that is the +% case! % \end{variable} % % This code uses internal functions with names that start with |\::| @@ -724,7 +722,7 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[int, EXP]{\::o} +% \begin{macro}[int, EXP]{\::o} % This function is used to expand an argument once. % \begin{macrocode} \cs_new:Npn \::o #1 \::: #2#3 diff --git a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx index 919281bd552..3816602c541 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3file.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3file.dtx 4059 2012-08-08 13:12:06Z bruno $ {L3 File and I/O operations} %</driver|package> %<*driver> @@ -207,7 +207,7 @@ % additive). % \end{function} % -% \begin{function}[updated = 2012-07-03] +% \begin{function}[updated = 2012-07-31] % {\ior_close:N, \ior_close:c, \iow_close:N, \iow_close:c} % \begin{syntax} % \cs{ior_close:N} \meta{stream} @@ -246,7 +246,7 @@ % \end{texnote} % \end{function} % -% \begin{function}[added = 2012-06-24]{\ior_get_str:NN} +% \begin{function}[added = 2012-06-24, updated = 2012-07-31]{\ior_get_str:NN} % \begin{syntax} % \cs{ior_get_str:NN} \meta{stream} \meta{token list variable} % \end{syntax} @@ -257,8 +257,10 @@ % category code $12$ (other), with the exception of space % characters which are given category code $10$ (space). % \begin{texnote} -% This protected macro expands to the \eTeX{} primitive \tn{readline} -% along with the |to| keyword. +% This protected macro is a wrapper around the \eTeX{} primitive +% \tn{readline}. However, the end-line character normally added by +% this primitive is not included in the result of +% \cs{ior_get_str:NN}. % \end{texnote} % \end{function} % @@ -490,7 +492,7 @@ % higher-level % functions which have already fully expanded the \meta{file name} and which % need to perform multiple open or close operations. See for example the -% implementation of \cs{file_add_path:Nn}, +% implementation of \cs{file_add_path:nN}, % \end{function} % % \end{documentation} @@ -1112,10 +1114,18 @@ % \end{macro} % % \begin{macro}{\ior_get_str:NN} -% Reading as strings is also a primitive wrapper. +% Reading as strings is a more complicated wrapper, as we wish to +% remove the endline character. % \begin{macrocode} \cs_new_protected:Npn \ior_get_str:NN #1#2 - { \etex_readline:D #1 to #2 } + { + \use:x + { + \int_set_eq:NN \tex_endlinechar:D \c_minus_one + \exp_not:n { \etex_readline:D #1 to #2 } + \int_set:Nn \tex_endlinechar:D { \int_use:N \tex_endlinechar:D } + } + } % \end{macrocode} % \end{macro} % @@ -1293,7 +1303,7 @@ { \int_compare:nNnF #1 > \c_fifteen { - \tex_closeout:D #1 + \tex_immediate:D \tex_closeout:D #1 \prop_gremove:NV \g_@@_streams_prop #1 \cs_gset_eq:NN #1 \c_term_iow } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx index 845d47814d5..9d023c21224 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3final.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3final.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Experimental format finalisation} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx index 981e642653b..92307fbacf7 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx @@ -35,8 +35,8 @@ %% % %<*driver> -\RequirePackage{l3names} -\GetIdInfo$Id: l3fp-assign.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3fp-assign.dtx 4082 2012-08-12 12:14:17Z bruno $ {L3 Floating-point assignments} \documentclass[full]{l3doc} \begin{document} @@ -156,16 +156,21 @@ % \fp_sub:Nn, \fp_sub:cn, \fp_gsub:Nn, \fp_gsub:cn, % } % \begin{macro}[aux]{\@@_add:NNNn} -% The auxiliary's arguments are 1: the assignment function, 2: the -% operation, 3: the fp variable, 4: the second operand. The -% parentheses around the second operand are needed because |+| and |-| -% are not the operations with the lowest priority. +% For the sake of error recovery we should not simply set |#1| to +% $|#1| \pm (|#2|)$: for instance, if |#2| is % ^^A( +% |0)+2|, the parsing error would be raised at the last closing +% parenthesis rather than at the closing parenthesis in the user +% argument. Thus we evaluate |#2| instead of just putting +% parentheses. As an optimization we use \cs{@@_parse:n} rather than +% \cs{fp_eval:n}, which would convert the result away from the +% internal representation and back. % \begin{macrocode} \cs_new_protected_nopar:Npn \fp_add:Nn { \@@_add:NNNn \fp_set:Nn + } \cs_new_protected_nopar:Npn \fp_gadd:Nn { \@@_add:NNNn \fp_gset:Nn + } \cs_new_protected_nopar:Npn \fp_sub:Nn { \@@_add:NNNn \fp_set:Nn - } \cs_new_protected_nopar:Npn \fp_gsub:Nn { \@@_add:NNNn \fp_gset:Nn - } -\cs_new_protected:Npn \@@_add:NNNn #1#2#3#4 { #1 #3 { #3 #2 (#4) } } +\cs_new_protected:Npn \@@_add:NNNn #1#2#3#4 + { #1 #3 { #3 #2 \@@_parse:n {#4} } } \cs_generate_variant:Nn \fp_add:Nn { c } \cs_generate_variant:Nn \fp_gadd:Nn { c } \cs_generate_variant:Nn \fp_sub:Nn { c } @@ -232,4 +237,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx index 566eec13ec5..2a26c63ada5 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx @@ -35,8 +35,8 @@ %% % %<*driver> -\RequirePackage{l3names} -\GetIdInfo$Id: l3fp-aux.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3fp-aux.dtx 4089 2012-08-14 04:52:20Z bruno $ {L3 Floating-point support functions} \documentclass[full]{l3doc} \begin{document} @@ -80,6 +80,34 @@ %<@@=fp> % \end{macrocode} % +% ^^A todo: make sanitize and pack more homogeneous between modules. +% +% ^^A begin[todo]: move +% \section{Internal storage of floating points numbers} +% +% A floating point number \meta{X} is stored as +% \begin{quote} +% \cs{s_@@} \cs{@@_chk:w} \meta{case} \meta{sign} \meta{body} |;| +% \end{quote} +% Here, \meta{case} is 0 for $\pm 0$, 1 for normal numbers, 2 for $\pm +% \infty$, and 3 for \texttt{nan}, and \meta{sign} is $0$ for positive +% numbers, $1$ for \texttt{nan}s, and $2$ for negative numbers. The +% \meta{body} of normal numbers is \Arg{exponent} \Arg{X_1} \Arg{X_2} +% \Arg{X_3} \Arg{X_4}, with +% \[ +% \meta{X} = (-1)^{\meta{sign}} 10^{-\meta{exponent}} \sum_i +% \meta{X_i} 10^{-4i}. +% \] +% Calculations are done in base $10000$, \emph{i.e.} one myriad. The +% \meta{exponent} lies between $\pm\cs{c_@@_max_exponent_int} = \pm +% \the\csname\detokenize{c__fp_max_exponent_int}\endcsname$ inclusive. +% +% Additionally, positive and negative floating point numbers may only be +% stored with $1000\leq\meta{X_1}<10000$. This requirement is necessary +% in order to preserve accuracy and speed. +% +% ^^A end[todo] +% % \subsection{Using arguments and semicolons} % % \begin{macro}[int, EXP]{\@@_use_none_stop_f:n} @@ -245,6 +273,16 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}[int, EXP]{\@@_neg_sign:N} +% When appearing in an integer expression or after \cs{__int_value:w}, +% this expands to the sign opposite to |#1|, namely $0$ (positive) is +% turned to $2$ (negative), $1$ (\texttt{nan}) to $1$, and $2$ to $0$. +% \begin{macrocode} +\cs_new:Npn \@@_neg_sign:N #1 + { \__int_eval:w \c_two - #1 \__int_eval_end: } +% \end{macrocode} +% \end{macro} +% % \subsection{Overflow, underflow, and exact zero} % %^^A todo: the sign of exact zeros should depend on the rounding mode. @@ -468,6 +506,27 @@ % \end{variable} % \end{macro} % +% \begin{macro}[int, EXP]{\@@_pack_Bigg:NNNNNNw} +% \begin{variable} +% { +% \c_@@_Bigg_trailing_shift_int , +% \c_@@_Bigg_middle_shift_int , +% \c_@@_Bigg_leading_shift_int , +% } +% This set of shifts allows for computations involving results in the +% range $[-1\cdot 10^{9}, 147483647]$; the end-point is $2^{31} - 1 - +% 2\cdot 10^{9} \simeq 1.47\cdot 10^{8}$. Shifted values all have +% exactly $10$ digits. +% \begin{macrocode} +\int_const:Nn \c_@@_Bigg_leading_shift_int { - 20 0000 } +\int_const:Nn \c_@@_Bigg_middle_shift_int { 20 0000 * 9999 } +\int_const:Nn \c_@@_Bigg_trailing_shift_int { 20 0000 * 10000 } +\cs_new:Npn \@@_pack_Bigg:NNNNNNw #1#2 #3#4#5#6 #7; + { + #1#2#3#4#5#6 ; {#7} } +% \end{macrocode} +% \end{variable} +% \end{macro} +% % \begin{macro}[int, EXP]{\@@_pack_twice_four:wNNNNNNNN} % \begin{syntax} % \cs{@@_pack_twice_four:wNNNNNNNN} \meta{tokens} |;| \meta{$\geq 8$ digits} @@ -482,6 +541,20 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}[int, EXP]{\@@_pack_eight:wNNNNNNNN} +% \begin{syntax} +% \cs{@@_pack_eight:wNNNNNNNN} \meta{tokens} |;| \meta{$\geq 8$ digits} +% \end{syntax} +% Grabs one set of $8$ digits and places them before the semi-colon +% delimiter as a single group. Putting several copies of this +% function before a semicolon will pack more digits since each will +% take the digits packed by the others in its first argument. +% \begin{macrocode} +\cs_new:Npn \@@_pack_eight:wNNNNNNNN #1; #2#3#4#5 #6#7#8#9 + { #1 {#2#3#4#5#6#7#8#9} ; } +% \end{macrocode} +% \end{macro} +% % \subsection{Decimate (dividing by a power of 10)} % % ^^A begin[todo] @@ -569,7 +642,7 @@ % The arguments are as follows: |#1| indicates which function is % being defined; after one step of expansion, |#2| yields the % \enquote{extra digits} which are then converted by -% \cs{@@_decimate_round:Nw} to the \meta{rounding} digit. +% \cs{@@_round_digit:Nw} to the \meta{rounding} digit. % This triggers the \texttt{f}-expansion of % \cs{@@_decimate_pack:nnnnnnnnnnw},\footnote{No, the argument % spec is not a mistake: the function calls an auxiliary to @@ -585,7 +658,7 @@ { \exp_after:wN ##1 \__int_value:w - \exp_after:wN \@@_decimate_round:Nw #2 ; + \exp_after:wN \@@_round_digit:Nw #2 ; \@@_decimate_pack:nnnnnnnnnnw #3 ; } } @@ -609,29 +682,19 @@ % \end{macro} % % \begin{macro}[EXP, aux] -% {\@@_decimate_round:Nw, \@@_decimate_pack:nnnnnnnnnnw} -% \cs{@@_decimate_round:Nw} will receive the \enquote{extra digits} +% {\@@_round_digit:Nw, \@@_decimate_pack:nnnnnnnnnnw} +% % ^^A \cs{@@_round_digit:Nw} moved to \pkg{l3fp-round}. +% \cs{@@_round_digit:Nw} will receive the \enquote{extra digits} % as its argument, and its expansion is triggered by \cs{__int_value:w}. % If the first digit is neither $0$ nor $5$, then it is the \meta{rounding} % digit. Otherwise, if the remaining digits are not all zero, we need % to add $1$ to that leading digit to get the rounding digit. Some caution % is required, though, because there may be more than $10$ % \enquote{extra digits}, and this may overflow \TeX{}'s integers. -% Instead of feeding the digits directly to \cs{@@_decimate_round:Nw}, +% Instead of feeding the digits directly to \cs{@@_round_digit:Nw}, % they come split into several blocks, separated by $+$. Hence the first % \cs{__int_eval:w} here. % \begin{macrocode} -\cs_new:Npn \@@_decimate_round:Nw #1 #2; - { - \if_int_odd:w \if_meaning:w 0 #1 \c_one \else: - \if_meaning:w 5 #1 \c_one \else: - \c_zero \fi: \fi: - \if_int_compare:w \__int_eval:w #2 > \c_zero - \__int_eval:w 1 + - \fi: - \fi: - #1 - } % \end{macrocode} % The computation of the \meta{rounding} digit leaves an unfinished % \cs{__int_value:w}, which expands the following functions. This @@ -706,7 +769,7 @@ % % \begin{macro}[int, EXP]{\@@_case_return_o:Nw} % This function ends a \TeX{} conditional, removes junk and a floating -% point, and returns its first argument, a \meta{fp~var}, expanding +% point, and returns its first argument (an \meta{fp~var}) then expands % once after it. % \begin{macrocode} \cs_new:Npn \@@_case_return_o:Nw #1#2 \fi: #3 \s_@@ #4 ; @@ -732,10 +795,13 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[int, EXP]{\@@_case_return_ii_o:ww} -% Similar to \cs{@@_case_return_same_o:w}, but this returns the second -% of two trailing floating point numbers, expanding once after it. +% \begin{macro}[int, EXP]{\@@_case_return_i_o:ww, \@@_case_return_ii_o:ww} +% Similar to \cs{@@_case_return_same_o:w}, but this returns the first +% or second of two trailing floating point numbers, expanding once +% after the result. % \begin{macrocode} +\cs_new:Npn \@@_case_return_i_o:ww #1 \fi: #2 \s_@@ #3 ; \s_@@ #4 ; + { \fi: \@@_exp_after_o:w \s_@@ #3 ; } \cs_new:Npn \@@_case_return_ii_o:ww #1 \fi: #2 \s_@@ #3 ; { \fi: \@@_exp_after_o:w } % \end{macrocode} @@ -763,7 +829,10 @@ % appearing in the case where the normal floating point is an integer % takes care of expanding all the conditionals until the trailing |;|. % That integer is fed to \cs{@@_small_int_true:wTF} which places it as -% a braced argument of the true branch. +% a braced argument of the true branch. The \cs{use_i:nn} in +% \cs{@@_small_int_test:NnnwNTF} removes the top-level \cs{else:} +% coming from \cs{@@_small_int_normal:NnwTF}, hence will call the +% \cs{use_iii:nnn} which follows, taking the false branch. % \begin{macrocode} \cs_new:Npn \@@_small_int:wTF \s_@@ \@@_chk:w #1 { @@ -796,7 +865,7 @@ \exp_after:wN \@@_small_int_true:wTF \__int_value:w \if_meaning:w 2 #5 - \fi: #3 \else: - \exp_after:wN \use_iii:nnn + \exp_after:wN \use_i:nn \fi: } % \end{macrocode} @@ -847,4 +916,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx index 0b06d377232..591ccf5615e 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx @@ -35,8 +35,8 @@ %% % %<*driver> -\RequirePackage{l3names} -\GetIdInfo$Id: l3fp-basics.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3fp-basics.dtx 4089 2012-08-14 04:52:20Z bruno $ {L3 Floating-point arithmetic} \documentclass[full]{l3doc} \begin{document} @@ -77,63 +77,34 @@ %<@@=fp> % \end{macrocode} % +% The \pkg{l3fp-basics} module implements addition, subtraction, +% multiplication, and division of two floating points, and the absolute +% value and sign-changing operations on one floating point. % All operations implemented in this module yield the outcome of % rounding the infinitely precise result of the operation to the -% nearest representable number. -% -% ^^A begin[todo]: move -% \section{Internal storage of floating points numbers} -% -% A floating point number \meta{X} is stored as -% \begin{quote} -% \cs{s_@@} \cs{@@_chk:w} \meta{case} \meta{sign} \meta{body} |;| -% \end{quote} -% Here, \meta{case} is 0 for $\pm 0$, 1 for normal numbers, 2 for $\pm -% \infty$, and 3 for \texttt{nan}, and \meta{sign} is $0$ for positive -% numbers, $1$ for \texttt{nan}s, and $2$ for negative numbers. The -% \meta{body} of normal numbers is \Arg{exponent} \Arg{X_1} \Arg{X_2} -% \Arg{X_3} \Arg{X_4}, with -% \[ -% \meta{X} = (-1)^{\meta{sign}} 10^{-\meta{exponent}} \sum_i -% \meta{X_i} 10^{-4i}. -% \] -% Calculations are done in base $10000$, \emph{i.e.} one myriad. The -% \meta{exponent} lies between $\pm\cs{c_@@_max_exponent_int} = \pm -% \the\csname\detokenize{c__fp_max_exponent_int}\endcsname$ inclusive. -% -% Additionally, positive and negative floating point numbers may only be -% stored with $1000\leq\meta{X_1}<10000$. This requirement is necessary -% in order to preserve accuracy and speed. -% -% ^^A end[todo] -% -% ^^A begin[todo] +% nearest floating point. % % Some algorithms used below end up being quite similar to some % described in \enquote{What Every Computer Scientist Should Know About % Floating Point Arithmetic}, by David Goldberg, which can be found at -% \texttt{http://cr.yp.to/2005-590/goldberg.pdf}. I need to compare them -% very carefully. -% -% ^^A end[todo] -% -%^^A todo sanitize, pack. +% \texttt{http://cr.yp.to/2005-590/goldberg.pdf}. % % \subsection{Common to several operations} % -% \begin{macro}[EXP] +% \begin{macro}[aux, EXP] % { -% \@@_basics_pack_low:NNNNNw , -% \@@_basics_pack_high:NNNNNw , +% \@@_basics_pack_low:NNNNNw, +% \@@_basics_pack_high:NNNNNw, % \@@_basics_pack_high_carry:w % } % Addition and multiplication of mantissas are done in two steps: -% first compute a (more or less) exact result, -% then round and pack digits in the final (braced) form. -% These functions take care of the packing, with special attention -% given to the case where rounding has caused a carry. -% In \cs{@@_basics_pack_high_carry:w}, |#1| should -% always be $0000$. +% first compute a (more or less) exact result, then round and pack +% digits in the final (braced) form. These functions take care of the +% packing, with special attention given to the case where rounding has +% caused a carry. Since rounding can only shift the final digit by +% $1$, a carry always produces an exact power of $10$. Thus, +% \cs{@@_basics_pack_high_carry:w} is always followed by four times +% |{0000}|. % \begin{macrocode} \cs_new:Npn \@@_basics_pack_low:NNNNNw #1 #2#3#4#5 #6; { @@ -154,284 +125,275 @@ % \end{macrocode} % \end{macro} % -% \begin{macro} +% \begin{macro}[aux, EXP] % { -% \@@_basics_return_nan_nan:NNww , -% \@@_basics_return_zero:NNww , -% \@@_basics_return_inf:NNww , -% \@@_basics_return_i:NNNNww , -% \@@_basics_return_ii:NNNNww , -% \@@_basics_return_nan:NNNNww +% \@@_basics_pack_weird_low:NNNNw, +% \@@_basics_pack_weird_high:NNNNNNNNw % } -% \begin{syntax} -% \cs{@@_basics_return_...:NNww} -% ~~\meta{sign_1} \meta{sign_2} \meta{body_1} |;| \meta{body_2} |;| -% \end{syntax} -% Used for binary operations, to return a value for some special -% cases (common to several operations). All functions expand once -% after their arguments. -% -% ^^A todo: redoc, changed. -% The \texttt{nan_nan} function combines the \texttt{info} fields -% of the two \texttt{nan}.\footnote{Bruno: check that messages are -% kept.} -% The \texttt{zero} and \texttt{inf} functions return $\pm 0$ or -% $\pm\infty$ with a sign equal to the product of the two signs: -% three \cs{exp_after:wN} are needed to escape out of the -% conditional, and expand once after. -% The \texttt{i} and \texttt{ii} functions return one of their -% operands and expand after using \cs{@@_exp_after_o:w}. -% In some cases, this could be optimized, since we know in advance -% what case of number we have. However, it seems better to keep the -% number of control sequences low: these functions are called only -% in special cases anyways, so performance is not an issue. +% I don't fully understand those functions, used for additions and +% divisions. Hence the name. % \begin{macrocode} -\cs_new:Npn \@@_basics_return_nan_nan:NNww #1#2 #3; #4; - { \@@_exp_after_o:w \s_@@ \@@_chk:w 3 1 #3 ; } -\cs_new:Npn \@@_basics_return_zero:NNww #1#2 #3; #4; - { - \if_meaning:w #1 #2 - \exp_after:wN \exp_after:wN \exp_after:wN \c_zero_fp - \else: - \exp_after:wN \exp_after:wN \exp_after:wN \c_minus_zero_fp - \fi: - } -\cs_new:Npn \@@_basics_return_inf:NNww #1#2 #3; #4; +\cs_new:Npn \@@_basics_pack_weird_low:NNNNw #1 #2#3#4 #5; { - \if_meaning:w #1 #2 - \exp_after:wN \exp_after:wN \exp_after:wN \c_inf_fp - \else: - \exp_after:wN \exp_after:wN \exp_after:wN \c_minus_inf_fp - \fi: - } -\cs_new:Npn \@@_basics_return_i:NNNNww #1#2 #3#4 #5; #6; - { \@@_exp_after_o:w \s_@@ \@@_chk:w #1 #3 #5; } -\cs_new:Npn \@@_basics_return_ii:NNNNww #1#2 #3#4 #5; #6; - { \@@_exp_after_o:w \s_@@ \@@_chk:w #2 #4 #6; } -\cs_new:Npn \@@_basics_return_nan:NNww #1#2 - { - \if_meaning:w 1 #1 - \exp_after:wN \@@_basics_return_i:NNNNww - \else: - \exp_after:wN \@@_basics_return_ii:NNNNww + \if_meaning:w 2 #1 + + \c_one \fi: - 3 3 #1 #2 + \__int_eval_end: + #2#3#4; {#5} ; } +\cs_new:Npn \@@_basics_pack_weird_high:NNNNNNNNw + 1 #1#2#3#4 #5#6#7#8 #9; { ; {#1#2#3#4} {#5#6#7#8} {#9} } % \end{macrocode} % \end{macro} % % \subsection{Addition and subtraction} % -% \begin{macro}[int, EXP]{\@@_+_o:ww} -% For addition, everything is easy. No need to grab the -% \meta{body_2}. -% \begin{macrocode} -\cs_new:cpn { @@_+_o:ww } - \s_@@ \@@_chk:w #1 #2 #3 ; \s_@@ \@@_chk:w #4 #5 - { \@@_add_cases:NN #1 #4 #2 #5 #3 ; } -% \end{macrocode} -% \end{macro} +% We define here two functions, \cs{@@_-_o:ww} and \cs{@@_+_o:ww}, which +% perform the subtraction and addition of their two floating point +% operands, and expand the tokens following the result once. +% +% A more obscure function, \cs{@@_add_big_i_o:wNww}, is used in +% \pkg{l3fp-expo}. +% +% The logic goes as follows: +% \begin{itemize} +% \item \cs{@@_-_o:ww} calls \cs{@@_+_o:ww} to do the work, with the +% sign of the second operand flipped; +% \item \cs{@@_+_o:ww} dispatches depending on the type of floating +% point, calling specialized auxiliaries; +% \item in all cases except summing two normal floating point numbers, +% we return one or the other operands depending on the signs, or +% detect an invalid operation in the case of $\infty - \infty$; +% \item for normal floating point numbers, compare the signs; +% \item to add two floating point numbers of the same sign or of +% opposite signs, shift the mantissa of the smaller one to match the +% bigger one, perform the addition or subtraction of mantissas, +% check for a carry, round, and pack using the +% |\__fp_basics_pack_...| functions. +% \end{itemize} +% The trickiest part is to round correctly when adding or subtracting +% normal floating point numbers. +% +% \subsubsection{Sign, exponent, and special numbers} % % \begin{macro}[int, EXP]{\@@_-_o:ww} -% Change the sign of the second argument. +% A previous version of this function grabbed its two operands, +% changed the sign of the second, and called \cs{@@_+_o:ww}. However, +% for efficiency reasons, the operands were swapped in the process, +% which means that error messages ended up wrong. Now, the +% \cs{@@_+_o:ww} auxiliary has a hook: it takes one argument between +% the first \cs{s_@@} and \cs{@@_chk:w}, which is applied to the sign +% of the second operand. Positioning the hook there means that +% \cs{@@_+_o:ww} can still check that it was followed by \cs{s_@@} and +% not arbitrary junk. % \begin{macrocode} -\cs_new:cpn { @@_-_o:ww } - \s_@@ \@@_chk:w #1 #2 #3 ; \s_@@ \@@_chk:w #4 #5 +\cs_new_nopar:cpx { @@_-_o:ww } \s_@@ { - \exp_after:wN \@@_add_cases:NN - \exp_after:wN #1 - \exp_after:wN #4 - \exp_after:wN #2 - \int_use:N \__int_eval:w \c_two - #5 \__int_eval_end: - #3 ; + \exp_not:c { @@_+_o:ww } + \exp_not:n { \s_@@ \@@_neg_sign:N } } % \end{macrocode} % \end{macro} % -% \subsubsection{Sign, exponent, and special numbers} -% -% \begin{macro}[EXP,aux]{\@@_add_cases:NN} -% \begin{syntax} -% \cs{@@_add_cases:NN} \meta{case_1} \meta{case_2} -% ~~\meta{sign_1} \meta{sign_2} \meta{body_1} |;| \meta{body_2} |;| -% \end{syntax} -% This performs the addition. it also expands the following tokens -% on the input stream once. -% -% Whenever \meta{case_1} is different from \meta{case_2}, the result -% is simply the floating point number with the highest \meta{case}. -% For instance, adding a normal number to a zero gives the normal -% number, and adding a \texttt{nan} to any non-\texttt{nan} gives -% that \texttt{nan}. Optimizing for addition of normal numbers, -% we test for equality and then separate the \enquote{greater than} -% and \enquote{less than} branches. +% \begin{macro}[int, EXP]{\@@_+_o:ww} +% This function is either called directly with an empty |#1| to +% compute an addition, or it is called by \cs{@@_-_o:ww} with +% \cs{@@_neg_sign:N} as |#1| to compute a subtraction (equivalent to +% changing the \meta{sign_2} of the second operand). If the +% \meta{types} |#2| and |#4| are the same, dispatch to case |#2| ($0$, +% $1$, $2$, or $3$), where we call specialized functions: thanks to +% \cs{__int_value:w}, those receive the tweaked \meta{sign_2} +% (expansion of |#1#5|) as an argument. If the \meta{types} are +% distinct, the result is simply the floating point number with the +% highest \meta{type}. Since case $3$ (used for two \texttt{nan}) +% also picks the first operand, we can also use it when \meta{type_1} +% is greater than \meta{type_2}. Also note that we don't need to +% worry about \meta{sign_2} in that case since the second operand is +% discarded. % \begin{macrocode} -\cs_new:Npn \@@_add_cases:NN #1 #2 +\cs_new:cpn { @@_+_o:ww } + \s_@@ #1 \@@_chk:w #2 #3 ; \s_@@ \@@_chk:w #4 #5 { - \if_int_compare:w #1 = #2 \exp_stop_f: - \exp_after:wN \@@_add_cases_eq:N - \else: - \if_int_compare:w #1 < #2 \exp_stop_f: - \exp_after:wN \exp_after:wN - \exp_after:wN \@@_basics_return_ii:NNNNww + \if_case:w + \if_meaning:w #2 #4 + #2 \exp_stop_f: \else: - \exp_after:wN \exp_after:wN - \exp_after:wN \@@_basics_return_i:NNNNww + \if_int_compare:w #2 > #4 \exp_stop_f: + \c_three + \else: + \c_minus_one + \fi: \fi: - \exp_after:wN #1 + \exp_after:wN \@@_add_zeros_o:Nww \__int_value:w + \or: \exp_after:wN \@@_add_normal_o:Nww \__int_value:w + \or: \exp_after:wN \@@_add_inf_o:Nww \__int_value:w + \or: \@@_case_return_i_o:ww + \else: \exp_after:wN \@@_add_return_ii_o:Nww \__int_value:w \fi: - #2 + #1 #5 + \s_@@ \@@_chk:w #2 #3 ; + \s_@@ \@@_chk:w #4 #5 } % \end{macrocode} -% If the first \meta{case} is larger, then the first number remains -% untouched, while the second number is ignored. On the other hand, -% if the second \meta{case} is larger, the opposite happens: we retain -% the second number. In both cases, there needs to be one step of -% expansion after. -% \begin{macrocode} -% \end{macrocode} -% We are then ready for the equality case: we split according -% to the \meta{case}. +% \end{macro} +% +% \begin{macro}[aux, EXP]{\@@_add_return_ii_o:Nww} +% Ignore the first operand, and return the second, but using the sign +% |#1| rather than |#4|. As usual, expand after the floating point. % \begin{macrocode} -\cs_new:Npn \@@_add_cases_eq:N #1 - { - \if_case:w #1 \exp_stop_f: - \exp_after:wN \@@_add_zeros:NNww - \or: \exp_after:wN \@@_add_normal:NNww - \or: \exp_after:wN \@@_add_inf:NNww - \or: \exp_after:wN \@@_basics_return_nan_nan:NNww - \fi: - } +\cs_new:Npn \@@_add_return_ii_o:Nww #1 #2 ; \s_@@ \@@_chk:w #3 #4 + { \@@_exp_after_o:w \s_@@ \@@_chk:w #3 #1 } % \end{macrocode} -% Adding two zeros yields \cs{c_zero_fp}, except if both -% zeros were $-0$.\footnote{Bruno: this should depend on the -% rounding mode.} +% \end{macro} +% +% \begin{macro}[aux, EXP]{\@@_add_zeros_o:Nww} +% Adding two zeros yields \cs{c_zero_fp}, except if both zeros were +% $-0$. % \begin{macrocode} -\cs_new:Npn \@@_add_zeros:NNww #1#2 #3; +\cs_new:Npn \@@_add_zeros_o:Nww #1 \s_@@ \@@_chk:w 0 #2 { - \if_int_compare:w #1 #2 = 02 \exp_stop_f: - \@@_case_return_o:Nw \c_zero_fp + \if_int_compare:w #2 #1 = 20 \exp_stop_f: + \exp_after:wN \@@_add_return_ii_o:Nww \else: - \@@_case_return_same_o:w + \@@_case_return_i_o:ww \fi: + #1 \s_@@ \@@_chk:w 0 #2 } % \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux, EXP]{\@@_add_inf_o:Nww} % If both infinities have the same sign, just return that infinity, -% otherwise, it is an invalid operation. +% otherwise, it is an invalid operation. We find out if that invalid +% operation is an addition or a subtraction by testing whether the +% tweaked \meta{sign_2} (|#1|) and the \meta{sign_2} (|#4|) are +% identical. % \begin{macrocode} -\cs_new:Npn \@@_add_inf:NNww #1#2 #3; +\cs_new:Npn \@@_add_inf_o:Nww + #1 \s_@@ \@@_chk:w 2 #2 #3; \s_@@ \@@_chk:w 2 #4 { \if_meaning:w #1 #2 - \@@_case_return_same_o:w + \@@_case_return_i_o:ww \else: \@@_case_use:nw { - \@@_invalid_operation:Nnww \c_nan_fp { + } - \s_@@ \@@_chk:w 2 #1 #3 ; + \if_meaning:w #1 #4 + \exp_after:wN \@@_invalid_operation_o:Nww + \exp_after:wN + + \else: + \exp_after:wN \@@_invalid_operation_o:Nww + \exp_after:wN - + \fi: } \fi: - \s_@@ \@@_chk:w 2 #2 + \s_@@ \@@_chk:w 2 #2 #3; + \s_@@ \@@_chk:w 2 #4 } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_add_normal:NNww} -% \begin{syntax} -% \cs{@@_add_normal:NNww} \meta{sign_1} \meta{sign_2} -% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;| -% \end{syntax} +% \begin{macro}[aux, EXP]{\@@_add_normal_o:Nww} +% \begin{quote} +% \cs{@@_add_normal_o:Nww} \meta{sign_2} +% \cs{s_@@} \cs{@@_chk:w} |1| \meta{sign_1} +% \meta{exp_1} \meta{body_1} |;| +% \cs{s_@@} \cs{@@_chk:w} |1| \meta{initial sign_2} +% \meta{exp_2} \meta{body_2} |;| +% \end{quote} % We now have two normal numbers to add, and we have to check signs % and exponents more carefully before performing the addition. % \begin{macrocode} -\cs_new:Npn \@@_add_normal:NNww #1#2 +\cs_new:Npn \@@_add_normal_o:Nww #1 \s_@@ \@@_chk:w 1 #2 { \if_meaning:w #1#2 - \exp_after:wN \@@_add_npos:Nnwnw + \exp_after:wN \@@_add_npos_o:NnwNnw \else: - \exp_after:wN \@@_sub_npos:Nnwnw + \exp_after:wN \@@_sub_npos_o:NnwNnw \fi: - #1 + #2 } % \end{macrocode} % \end{macro} % % \subsubsection{Absolute addition} % -% In this subsection, we perform the addition -% of two positive normal numbers. +% In this subsection, we perform the addition of two positive normal +% numbers. % -% \begin{macro}[EXP]{\@@_add_npos:Nnwnw} -% \begin{syntax} -% \cs{@@_add_npos:Nnwnw} \meta{sign} -% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;| -% \end{syntax} -% Since we are doing an addition, \meta{sign} will be the final sign. -% The only special case which may arise is the case of an overflow. -% This will be checked by \cs{@@_sanitize:Nw} at the end of -% the calculation. We start an \cs{__int_eval:w}, responsible for -% computing the exponent, which may receive a contribution of |+1| -% in case of carry. The exponent should be stopped by |;| followed by -% the overall \meta{sign} for the sanitizing to work properly. -% -% Grab and compare the exponents. The smaller number is decimated until -% its exponent reaches that of the bigger number. We need to bring the -% final sign down in the midst of the calculation to do the rounding -% correctly. +% \begin{macro}[aux, EXP]{\@@_add_npos_o:NnwNnw} +% \begin{quote} +% \cs{@@_add_npos_o:NnwNnw} \meta{sign_1} \meta{exp_1} \meta{body_1} +% |;| \cs{s_@@} \cs{@@_chk:w} |1| \meta{initial sign_2} \meta{exp_2} +% \meta{body_2} |;| +% \end{quote} +% Since we are doing an addition, the final sign is \meta{sign_1}. +% Start an \cs{__int_eval:w}, responsible for computing the exponent: +% the result, and the \meta{final sign} are then given to +% \cs{@@_sanitize:Nw} which checks for overflow. The exponent is +% computed as the largest exponent |#2| or |#5|, incremented if there +% is a carry. To add the mantissas, we decimate the smaller number by +% the difference between the exponents. This is done by +% \cs{@@_add_big_i:wNww} or \cs{@@_add_big_ii:wNww}. We need to bring +% the final sign with us in the midst of the calculation to round +% properly at the end. % \begin{macrocode} -\cs_new:Npn \@@_add_npos:Nnwnw #1 #2#3; #4 +\cs_new:Npn \@@_add_npos_o:NnwNnw #1#2#3 ; \s_@@ \@@_chk:w 1 #4 #5 { \exp_after:wN \@@_sanitize:Nw \exp_after:wN #1 \int_use:N \__int_eval:w - \if_int_compare:w #2 > #4 \exp_stop_f: + \if_int_compare:w #2 > #5 \exp_stop_f: #2 - \exp_after:wN \@@_add_big_i:wNww \__int_value:w - + \exp_after:wN \@@_add_big_i_o:wNww \__int_value:w - \else: - #4 - \exp_after:wN \@@_add_big_ii:wNww \__int_value:w + #5 + \exp_after:wN \@@_add_big_ii_o:wNww \__int_value:w \fi: - \__int_eval:w #4 - #2 ; #1 #3; + \__int_eval:w #5 - #2 ; #1 #3; } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_add_big_i:wNww, -% \@@_add_big_ii:wNww} -% \begin{syntax} -% \cs{@@_add_big_i:wNww} \meta{shift} |;| \meta{sign} -% ~~\meta{body_1} |;| \meta{body_2} |;| -% \end{syntax} -% Shift the mantissa of the small number, and then add with -% \cs{@@_add_mantissa:NnnwnnnnN}. +% \begin{macro}[int, rEXP]{\@@_add_big_i_o:wNww} +% \begin{macro}[aux, rEXP]{\@@_add_big_ii_o:wNww} +% \begin{quote} +% \cs{@@_add_big_i_o:wNww} \meta{shift} |;| \meta{final sign} +% \meta{body_1} |;| \meta{body_2} |;| +% \end{quote} +% Shift the mantissa of the small number, then add with +% \cs{@@_add_mantissa_o:NnnwnnnnN}. % \begin{macrocode} -\cs_new:Npn \@@_add_big_i:wNww #1; #2 #3; #4; +\cs_new:Npn \@@_add_big_i_o:wNww #1; #2 #3; #4; { \@@_decimate:nNnnnn {#1} - \@@_add_mantissa:NnnwnnnnN + \@@_add_mantissa_o:NnnwnnnnN #4 #3 #2 } -\cs_new:Npn \@@_add_big_ii:wNww #1; #2 #3; #4; +\cs_new:Npn \@@_add_big_ii_o:wNww #1; #2 #3; #4; { \@@_decimate:nNnnnn {#1} - \@@_add_mantissa:NnnwnnnnN + \@@_add_mantissa_o:NnnwnnnnN #3 #4 #2 } % \end{macrocode} % \end{macro} +% \end{macro} % -% \begin{macro}{\@@_add_mantissa:NnnwnnnnN} -% \begin{syntax} -% \cs{@@_add_mantissa:NnnwnnnnN} -% ~~\meta{rounding} -% ~~\Arg{Y'_1} \Arg{Y'_2} \meta{extra-digits} |;| -% ~~\Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} -% ~~\meta{final sign} -% \end{syntax} +% \begin{macro}[aux, rEXP]{\@@_add_mantissa_o:NnnwnnnnN} +% \begin{macro}[aux, rEXP] +% {\@@_add_mantissa_pack:NNNNNNN, \@@_add_mantissa_test_o:N} +% \begin{quote} +% \cs{@@_add_mantissa_o:NnnwnnnnN} +% \meta{rounding digit} +% \Arg{Y'_1} \Arg{Y'_2} \meta{extra-digits} |;| +% \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} +% \meta{final sign} +% \end{quote} % To round properly, we must know at which digit the rounding % should occur. This requires to know whether the addition % produces an overall carry or not. Thus, we do the computation @@ -441,45 +403,43 @@ % give an exact power of $10$, for which it is easy to correct % the result at the end. % \begin{macrocode} -\cs_new:Npn \@@_add_mantissa:NnnwnnnnN #1 #2#3 #4; #5#6#7#8 +\cs_new:Npn \@@_add_mantissa_o:NnnwnnnnN #1 #2#3 #4; #5#6#7#8 { - \exp_after:wN \@@_add_mantissa_test:N + \exp_after:wN \@@_add_mantissa_test_o:N \int_use:N \__int_eval:w 1#5#6 + #2 \exp_after:wN \@@_add_mantissa_pack:NNNNNNN \int_use:N \__int_eval:w 1#7#8 + #3 ; #1 } -% \end{macrocode} -% -% \begin{macrocode} \cs_new:Npn \@@_add_mantissa_pack:NNNNNNN #1 #2#3#4#5#6#7 { - \if:w 2 #1 + \if_meaning:w 2 #1 + \c_one \fi: ; #2 #3 #4 #5 #6 #7 ; } -\cs_new:Npn \@@_add_mantissa_test:N #1 +\cs_new:Npn \@@_add_mantissa_test_o:N #1 { - \if:w 2 #1 - \exp_after:wN \@@_add_mantissa_carry:wwNNNN + \if_meaning:w 2 #1 + \exp_after:wN \@@_add_mantissa_carry_o:wwwNN \else: - \exp_after:wN \@@_add_mantissa_no_carry:wwNNNN + \exp_after:wN \@@_add_mantissa_no_carry_o:wwwNN \fi: } % \end{macrocode} +% \end{macro} +% \end{macro} % +% \begin{macro}[aux, rEXP]{\@@_add_mantissa_no_carry_o:wwwNN} % \begin{quote} -% \cs{@@_add_mantissa_no_carry:wwNNNN} -% ~~\meta{8d} |;| \meta{6d} |;| \meta{2d} |;| -% ~~\meta{rounding} \meta{sign} +% \cs{@@_add_mantissa_no_carry_o:wwwNN} +% \meta{8d} |;| \meta{6d} |;| \meta{2d} |;| +% \meta{rounding digit} \meta{sign} % \end{quote} -% If there's no carry, grab all the digits again, and just -% set the rounding correctly.\footnote{Bruno: an optimization -% would be to compute whether we need rounding or not, -% and only grab digits if there is rounding.} -% +% If there's no carry, grab all the digits again and round. The +% packing function \cs{@@_basics_pack_high:NNNNNw} takes care of the +% case where rounding brings a carry. % \begin{macrocode} -\cs_new:Npn \@@_add_mantissa_no_carry:wwNNNN +\cs_new:Npn \@@_add_mantissa_no_carry_o:wwwNN #1; #2; #3#4 ; #5#6 { \exp_after:wN \@@_basics_pack_high:NNNNNw @@ -490,328 +450,407 @@ \exp_after:wN ; } % \end{macrocode} +% \end{macro} % -% The case where there is a carry is very similar: rounding can even -% raise the first digit from $1$ to $2$ (but we don't need to check that). +% \begin{macro}[aux, rEXP]{\@@_add_mantissa_carry_o:wwwNN} % \begin{quote} -% \cs{@@_add_mantissa_carry:wwNNNN} -% ~~\meta{8d} |;| \meta{6d} |;| \meta{2d} |;| -% ~~\meta{rounding} \meta{sign} +% \cs{@@_add_mantissa_carry_o:wwwNN} +% \meta{8d} |;| \meta{6d} |;| \meta{2d} |;| +% \meta{rounding digit} \meta{sign} % \end{quote} +% The case where there is a carry is very similar. Rounding can even +% raise the first digit from $1$ to $2$, but we don't care. % \begin{macrocode} -\cs_new:Npn \@@_add_mantissa_carry:wwNNNN +\cs_new:Npn \@@_add_mantissa_carry_o:wwwNN #1; #2; #3#4; #5#6 { + \c_one - \exp_after:wN \@@_add_mantissa_carry_pack:NNNNNNNNw - \int_use:N \__int_eval:w 1 #1 - \exp_after:wN \@@_add_mantissa_carry_pack_ii:NNNNw - \int_use:N \__int_eval:w 1 #2#3 - + \@@_round:NNNN #6 #3 #4 #5 + \exp_after:wN \@@_basics_pack_weird_high:NNNNNNNNw + \int_use:N \__int_eval:w 1 1 #1 + \exp_after:wN \@@_basics_pack_weird_low:NNNNw + \int_use:N \__int_eval:w 1 #2#3 + + \exp_after:wN \@@_round:NNN + \exp_after:wN #6 + \exp_after:wN #3 + \__int_value:w \@@_round_digit:Nw #4 #5 ; \exp_after:wN ; } -\cs_new:Npn \@@_add_mantissa_carry_pack_ii:NNNNw #1 #2#3#4 #5; - { - \if:w 2 #1 - + \c_one - \fi: - \__int_eval_end: - #2#3#4; {#5} ; - } -\cs_new:Npn \@@_add_mantissa_carry_pack:NNNNNNNNw - #1#2#3#4 #5#6#7#8 #9; { ; {#1#2#3#4} {#5#6#7#8} {#9} } % \end{macrocode} % \end{macro} % % \subsubsection{Absolute subtraction} % -% \begin{macro}[EXP]{\@@_sub_npos:Nnwnw} -% \begin{syntax} -% \cs{@@_sub_npos:Nnwnw} \meta{sign} -% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;| -% \end{syntax} -% Rounding properly in some modes requires to know what the sign -% of the result will be. For addition, this was easy. Here, besides -% comparing the exponents to know how to decimate, we need to -% check carefully which number is bigger when they have the same -% exponent. +% \begin{macro}[aux, EXP]{\@@_sub_npos_o:NnwNnw} +% \begin{macro}[aux, EXP]{\@@_sub_eq_o:Nnwnw, \@@_sub_npos_ii_o:Nnwnw} +% \begin{quote} +% \cs{@@_sub_npos_o:NnwNnw} +% \meta{sign_1} \meta{exp_1} \meta{body_1} |;| +% \cs{s_@@} \cs{@@_chk:w} |1| +% \meta{initial sign_2} \meta{exp_2} \meta{body_2} |;| +% \end{quote} +% Rounding properly in some modes requires to know what the sign of +% the result will be. Thus, we start by comparing the exponents and +% mantissas. If the numbers coincide, return zero. If the second +% number is larger, swap the numbers and call +% \cs{@@_sub_npos_i_o:Nnwnw} with the opposite of \meta{sign_1}. % \begin{macrocode} -\cs_new:Npn \@@_sub_npos:Nnwnw #1 #2#3; #4 #5; +\cs_new:Npn \@@_sub_npos_o:NnwNnw #1#2#3; \s_@@ \@@_chk:w 1 #4#5#6; { - \exp_after:wN \@@_sanitize:wN - \int_use:N \__int_eval:w - \if_int_compare:w #2 > #4 \exp_stop_f: - #2 - \exp_after:wN \@@_sub_big_i:wNww \__int_value:w - - \else: - #4 - \if_int_compare:w #2 = #4 \exp_stop_f: - \@@_sub_exponent_eq:nnnnnnnn #3 #5 - \else: - \exp_after:wN \@@_sub_big_ii:wNww \__int_value:w - \fi: - \fi: - \__int_eval:w #4 - #2 ; #1 #3; #5; + \if_case:w \@@_compare_npos:nwnw {#2} #3; {#5} #6; \exp_stop_f: + \exp_after:wN \@@_sub_eq_o:Nnwnw + \or: + \exp_after:wN \@@_sub_npos_i_o:Nnwnw + \else: + \exp_after:wN \@@_sub_npos_ii_o:Nnwnw + \fi: + #1 {#2} #3; {#5} #6; + } +\cs_new:Npn \@@_sub_eq_o:Nnwnw #1#2; #3; { \exp_after:wN \c_zero_fp } +\cs_new:Npn \@@_sub_npos_ii_o:Nnwnw #1 #2; #3; + { + \exp_after:wN \@@_sub_npos_i_o:Nnwnw + \int_use:N \__int_eval:w \c_two - #1 \__int_eval_end: + #3; #2; } % \end{macrocode} % \end{macro} +% \end{macro} % -% \begin{macro}{\@@_sub_exponent_eq:nnnnnnnn} +% \begin{macro}[aux, EXP]{\@@_sub_npos_i_o:Nnwnw} +% After the computation is done, \cs{@@_sanitize:Nw} checks for +% overflow/underflow. It expects the \meta{final sign} and the +% \meta{exponent} (delimited by |;|). Start an integer expression for +% the exponent, which starts with the exponent of the largest number, +% and may be decreased if the two numbers are very close. If the two +% numbers have the same exponent, call the \texttt{near} auxiliary. +% Otherwise, decimate $y$, then call the \texttt{far} auxiliary to +% evaluate the difference between the two mantissas. Note that we +% decimate by $1$ less than one could expect. % \begin{macrocode} -\cs_new:Npn \@@_sub_exponent_eq:nnnnnnnn #1#2#3#4 #5#6#7#8 +\cs_new:Npn \@@_sub_npos_i_o:Nnwnw #1 #2#3; #4#5; { - \if_int_compare:w #1#2 > #5#6 \exp_stop_f: - \exp_after:wN \@@_sub_big_i:wNww \__int_value:w - \else: - \if_int_compare:w #1#2 < #5#6 \exp_stop_f: - \exp_after:wN \@@_sub_big_ii:wNww \__int_value:w + \exp_after:wN \@@_sanitize:Nw + \exp_after:wN #1 + \int_use:N \__int_eval:w + #2 + \if_int_compare:w #2 = #4 \exp_stop_f: + \exp_after:wN \@@_sub_back_near_o:nnnnnnnnN \else: - \if_int_compare:w #3#4 > #7#8 \exp_stop_f: - \exp_after:wN \@@_sub_big_i:wNww \__int_value:w - \else: - \if_int_compare:w #3#4 < #7#8 \exp_stop_f: - \exp_after:wN \@@_sub_big_ii:wNww \__int_value:w - \else: - \exp_after:wN \@@_sub_eq:wNww \__int_value:w - \fi: - \fi: + \exp_after:wN \@@_decimate:nNnnnn \exp_after:wN + { \int_use:N \__int_eval:w #2 - #4 - \c_one \exp_after:wN } + \exp_after:wN \@@_sub_back_far_o:NnnwnnnnN \fi: - \fi: + #5 + #3 + #1 } -\cs_new:Npn \@@_sub_eq:wNww #1; #2 #3; #4; - { \exp_after:wN ; \exp_after:wN 1 \exp_after:wN ; } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_sub_big_i:wNww,\@@_sub_big_ii:wNww} -% \begin{syntax} -% \cs{@@_sub_big_i:wNww} \meta{shift} |;| \meta{sign} -% ~~\meta{body_1} |;| \meta{body_2} |;| -% \end{syntax} -% Shift the mantissa of the small number, and then subtract with -% \cs{@@_sub_back_mantissa:NnnwNnnnn}. +% \begin{macro}[aux, rEXP]{\@@_sub_back_near_o:nnnnnnnnN} +% \begin{macro}[aux, rEXP] +% {\@@_sub_back_near_pack:NNNNNNw, \@@_sub_back_near_after:wNNNNw} +% \begin{quote} +% \cs{@@_sub_back_near_o:nnnnnnnnN} +% \Arg{Y_1} \Arg{Y_2} \Arg{Y_3} \Arg{Y_4} +% \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} +% \meta{final sign} +% \end{quote} +% In this case, the subtraction is exact, so we discard the +% \meta{final sign} |#9|. The very large shifts of $10^{9}$ and +% $1.1\cdot10^{9}$ are unnecessary here, but allow the auxiliaries to +% be reused later. Each integer expression produces a $10$ digit +% result. If the resulting $16$ digits start with a $0$, then we need +% to shift the group, padding with trailing zeros. % \begin{macrocode} -\cs_new:Npn \@@_sub_big_i:wNww #1; #2 #3; #4; +\cs_new:Npn \@@_sub_back_near_o:nnnnnnnnN #1#2#3#4 #5#6#7#8 #9 { - \@@_decimate:nNnnnn {#1} - \@@_sub_back_mantissa:NnnwNnnnn - #4 - #2 - #3 + \exp_after:wN \@@_sub_back_near_after:wNNNNw + \int_use:N \__int_eval:w 10#5#6 - #1#2 - \c_eleven + \exp_after:wN \@@_sub_back_near_pack:NNNNNNw + \int_use:N \__int_eval:w 11#7#8 - #3#4 \exp_after:wN ; } -\cs_new:Npn \@@_sub_big_ii:wNww #1; #2 #3; #4; +\cs_new:Npn \@@_sub_back_near_pack:NNNNNNw #1#2#3#4#5#6#7 ; + { + #1#2 ; {#3#4#5#6} {#7} ; } +\cs_new:Npn \@@_sub_back_near_after:wNNNNw 10 #1#2#3#4 #5 ; { - \exp_after:wN \@@_sub_big_i:wNww - \__int_value:w #1 \exp_after:wN ; - \int_use:N \__int_eval:w 2 - #2 \__int_eval_end: - #4; #3; + \if_meaning:w 0 #1 + \exp_after:wN \@@_sub_back_shift:wnnnn + \fi: + ; {#1#2#3#4} {#5} } % \end{macrocode} % \end{macro} +% \end{macro} % -% \begin{macro}{\@@_sub_back_mantissa:NnnwNnnnn} -% \begin{syntax} -% \cs{@@_sub_back_mantissa:NnnwNnnnn} -% ~~\meta{rounding} \Arg{Y'_1} \Arg{Y'_2} \meta{extra-digits} -% ~~\meta{final sign} -% ~~\Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} -% \end{syntax} -% At this stage, we know that \meta{Y} is less than \meta{X}, -% and we know the final sign. +% \begin{macro}[aux, rEXP]{\@@_sub_back_shift:wnnnn} +% \begin{macro}[aux, rEXP] +% { +% \@@_sub_back_shift_ii:ww, +% \@@_sub_back_shift_iii:NNNNNNNNw, +% \@@_sub_back_shift_iv:nnnnw +% } +% \begin{quote} +% \cs{@@_sub_back_shift:wnnnn} |;| +% \Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} |;| +% \end{quote} +% This function is called with $\meta{Z_1}\leq 999$. Act with +% \tn{number} to trim leading zeros from \meta{Z_1} \meta{Z_2} (we +% don't do all four blocks at once, since non-zero blocks would then +% overflow \TeX{}'s integers). If the first two blocks are zero, the +% auxiliary receives an empty |#1| and trims |#2#30| from leading +% zeros, yielding a total shift between $7$ and~$16$ to the exponent. +% Otherwise we get the shift from |#1| alone, yielding a result +% between $1$ and~$6$. Once the exponent is taken care of, trim +% leading zeros from |#1#2#3| (when |#1| is empty, the space before +% |#2#3| is ignored), get four blocks of $4$~digits and finally clean +% up. Trailing zeros are added so that digits can be grabbed safely. % \begin{macrocode} -\cs_new:Npn \@@_sub_back_mantissa:NnnwNnnnn #1 #2#3 #4; #5 #6#7#8#9 +\cs_new:Npn \@@_sub_back_shift:wnnnn ; #1#2 { - \exp_after:wN \@@_sub_back_mantissa_i:NNwNNNNwN - \exp_after:wN #1 - \exp_after:wN #5 - \int_use:N \__int_eval:w 2#6#7 - #2 - \c_two + - \exp_after:wN \@@_sub_back_mantissa_round:wNN - \int_use:N \__int_eval:w 2#8#9 - #3 ; #1 #5 + \exp_after:wN \@@_sub_back_shift_ii:ww + \__int_value:w #1 #2 0 ; } -% \end{macrocode} -% After the computation, we need to check whether the first digit of -% the result is zero. This can only happen if the two numbers had the -% same exponent, or exponents differing by $1$. In the latter case, -% the \meta{rounding} digit is not quite enough to let us retrieve -% the exact result (consider $\cdots25$ and $\cdots15$, both rounded -% to $\cdots2$ in the usual mode), so we also move the result of -% \cs{@@_round_neg:NNN} upstream as the digit $0$ or $1$. -% \begin{macrocode} -\cs_new:Npn \@@_sub_back_mantissa_round:wNN #1; #2 #3 +\cs_new:Npn \@@_sub_back_shift_ii:ww #1 0 ; #2#3 ; { - \exp_after:wN \@@_sub_back_mantissa_iii:N - \__int_value:w - \exp_after:wN \@@_round_neg:NNN - \exp_after:wN #3 - \use_none:nnnnnnnn #1 #2 - + #1 + \if_meaning:w @ #1 @ + - \c_seven + - \exp_after:wN \use_i:nnn + \exp_after:wN \@@_sub_back_shift_iii:NNNNNNNNw + \__int_value:w #2#3 0 ~ 123456789; + \else: + - \@@_sub_back_shift_iii:NNNNNNNNw #1 123456789; + \fi: + \exp_after:wN \@@_pack_twice_four:wNNNNNNNN + \exp_after:wN \@@_pack_twice_four:wNNNNNNNN + \exp_after:wN \@@_sub_back_shift_iv:nnnnw \exp_after:wN ; + \__int_value:w + #1 ~ #2#3 0 ~ 0000 0000 0000 000 ; } -\cs_new:Npn \@@_sub_back_mantissa_iii:N #1 - { - \exp_after:wN \@@_sub_back_mantissa_ii:NNNNNNw - \exp_after:wN #1 - \int_use:N \__int_eval:w - - #1 - } -\cs_new:Npn \@@_sub_back_mantissa_ii:NNNNNNw #1 #2 #3#4#5#6 #7; - { #2 ; #1 {#3#4#5#6} {#7} ; } +\cs_new:Npn \@@_sub_back_shift_iii:NNNNNNNNw #1#2#3#4#5#6#7#8#9; {#8} +\cs_new:Npn \@@_sub_back_shift_iv:nnnnw #1 ; #2 ; { ; #1 ; } % \end{macrocode} % \end{macro} +% \end{macro} % -% \begin{macro}{\@@_sub_back_mantissa_i:NNwNNNNwN} -% Here, |#3| should always be $2$, but we have to take is -% as a normal undelimited argument since that would break -% if |#2| is $2$. +% \begin{macro}[aux, rEXP]{\@@_sub_back_far_o:NnnwnnnnN} +% \begin{quote} +% \cs{@@_sub_back_far_o:NnnwnnnnN} +% \meta{rounding} \Arg{Y'_1} \Arg{Y'_2} \meta{extra-digits} |;| +% \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} +% \meta{final sign} +% \end{quote} +% If the difference is greater than $10^{\meta{expo_x}}$, call the +% \texttt{very_far} auxiliary. If the result is less than +% $10^{\meta{expo_x}}$, call the \texttt{not_far} auxiliary. If it is +% too close a call to know yet, namely if $1 \meta{Y'_1} \meta{Y'_2} = +% \meta{X_1} \meta{X_2} \meta{X_3} \meta{X_4} 0$, then call the +% \texttt{quite_far} auxiliary. We use the odd combination of space +% and semi-colon delimiters to allow the \texttt{not_far} auxiliary to +% grab each piece individually, the \texttt{very_far} auxiliary to use +% \cs{@@_pack_eight:wNNNNNNNN}, and the \texttt{quite_far} to ignore +% the mantissas easily (using the |;| delimiter). % \begin{macrocode} -\cs_new:Npn \@@_sub_back_mantissa_i:NNwNNNNwN #1#2 #3 #4#5#6#7 #8; #9 +\cs_new:Npn \@@_sub_back_far_o:NnnwnnnnN #1 #2#3 #4; #5#6#7#8 { - \if:w 0 #4 - \exp_after:wN \@@_sub_back_carry:NNwNnnnn - \exp_after:wN #1 - \exp_after:wN #9 + \if_case:w + \if_int_compare:w 1 #2 = #5#6 \use_i:nnnn #7 \exp_stop_f: + \if_int_compare:w #3 = \use_none:n #7#8 0 \exp_stop_f: + \c_zero + \else: + \if_int_compare:w #3 > \use_none:n #7#8 0 - \fi: \c_one + \fi: + \else: + \if_int_compare:w 1 #2 > #5#6 \use_i:nnnn #7 - \fi: \c_one + \fi: + \exp_after:wN \@@_sub_back_quite_far_o:wwNN + \or: \exp_after:wN \@@_sub_back_very_far_o:wwwwNN + \else: \exp_after:wN \@@_sub_back_not_far_o:wwwwNN \fi: - ; #2 - {#4#5#6#7} {#8} + #2 ~ #3 ; #5 #6 ~ #7 #8 ; #1 } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_sub_back_carry:NNwNnnnn} -% \begin{syntax} -% \cs{@@_sub_back_carry:NNwNnnnn} -% ~~\meta{rounding} \meta{0 or 1} |;| \meta{final sign} -% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} |;| -% \end{syntax} -% This function is called when $\meta{Z_1}\leq 999$. We revert -% the carry, which is given by \meta{0 or 1}, and subtract the -% \meta{rounding} digit as appropriate, then feed the result, -% of the form \meta{$\leq$ 7d} |;| \meta{9d} |;| to -% \cs{@@_sub_back_carry_i:wwN}. The result is always exact. +% \begin{macro}[aux, EXP]{\@@_sub_back_quite_far_o:wwNN} +% \begin{macro}[aux, EXP]{\@@_sub_back_quite_far_ii:NN} +% The easiest case is when $x-y$ is extremely close to a power of +% $10$, namely the first digit of $x$ is $1$, and all others vanish +% when subtracting $y$. Then the \meta{rounding} |#3| and the +% \meta{final sign} |#4| control whether we get $1$ or $0.9999 9999 +% 9999 9999$. In the usual round-to-nearest mode, we will get $1$ +% whenever the \meta{rounding} digit is less than or equal to $5$ +% (remember that the \meta{rounding} digit is only equal to $5$ if +% there was no further non-zero digit). % \begin{macrocode} -\cs_new:Npn \@@_sub_back_carry:NNwNnnnn #1#2 ; #3 #4#5#6#7 ; +\cs_new:Npn \@@_sub_back_quite_far_o:wwNN #1; #2; #3#4 { - \exp_after:wN \@@_sub_back_carry_i:wwN - \int_use:N \__int_eval:w #4 #5 - 1 + \exp_after:wN \@@_use_s:n - \int_use:N \__int_eval:w 1 #6 #7 0 + #2 0 - #1 ; #3 + \exp_after:wN \@@_sub_back_quite_far_ii:NN + \exp_after:wN #3 + \exp_after:wN #4 } -% \end{macrocode} -% Unless the first block is zero, check how many digits is has, -% and shift the exponent down by the corresponding amount. Then -% pack digits into blocks of $4$ (there are between $10$ and $16$ -% digits in front of \cs{@@_sub_back_carry_large:NNNNNNNNw}). -% \begin{macrocode} -\cs_new:Npn \@@_sub_back_carry_i:wwN #1 ; +\cs_new:Npn \@@_sub_back_quite_far_ii:NN #1#2 { - \if:w 0 #1 - - 8 - \exp_after:wN \@@_sub_back_carry_small:wN \__int_value:w + \if_case:w \@@_round_neg:NNN #2 0 #1 + \exp_after:wN \use_i:nn \else: - - \@@_sub_back_carry_ii:NNNNNNNNw #1 1234567; - \exp_after:wN \@@_sub_back_carry_large:NNNNNNNNw + \exp_after:wN \use_ii:nn \fi: - #1 + { ; {1000} {0000} {0000} {0000} ; } + { - \c_one ; {9999} {9999} {9999} {9999} ; } } % \end{macrocode} -% The case where the number is non-zero is slightly easier. +% \end{macro} +% \end{macro} +% +% \begin{macro}[aux, rEXP]{\@@_sub_back_not_far_o:wwwwNN} +% In the present case, $x$ and $y$ have different exponents, but +% $y$~is large enough that $x-y$ has a smaller exponent than~$x$. +% Decrement the exponent (with |- \c_one|). Then proceed in a way +% similar to the \texttt{near} auxiliaries seen earlier, but +% multiplying $x$ by~$10$ (|#30| and |#40| below), and with the added +% quirk that the \meta{rounding} digit has to be taken into account. +% Namely, we may have to decrease the result by one unit if +% \cs{@@_round_neg:NNN} returns~$1$. This function expects the +% \meta{final sign}~|#6|, the last digit of |1100000000+#40-#2|, and +% the \meta{rounding} digit. Instead of redoing the computation for +% the second argument, we note that \cs{@@_round_neg:NNN} only cares +% about its parity, which is identical to that of the last digit +% of~|#2|. % \begin{macrocode} -\cs_new:Npn \@@_sub_back_carry_ii:NNNNNNNNw #1#2#3#4#5#6#7#8#9; {#8} -\cs_new:Npn \@@_sub_back_carry_large:NNNNNNNNw #1#2#3#4 #5#6#7#8 #9; +\cs_new:Npn \@@_sub_back_not_far_o:wwwwNN #1 ~ #2; #3 ~ #4; #5#6 { - \@@_sub_back_carry_large_ii:NNNNNNNNw - #9 000000 ; {#1#2#3#4} {#5#6#7#8} + - \c_one + \exp_after:wN \@@_sub_back_near_after:wNNNNw + \int_use:N \__int_eval:w 1#30 - #1 - \c_eleven + \exp_after:wN \@@_sub_back_near_pack:NNNNNNw + \int_use:N \__int_eval:w 11 0000 0000 + #40 - #2 + - \exp_after:wN \@@_round_neg:NNN + \exp_after:wN #6 + \use_none:nnnnnnn #2 #5 + \exp_after:wN ; } -\cs_new:Npn \@@_sub_back_carry_large_ii:NNNNNNNNw #1#2#3#4 #5#6#7#8 #9; - { \@@_sub_back_carry_large_iii:nnnnN {#1#2#3#4} {#5#6#7#8} } -\cs_new:Npn \@@_sub_back_carry_large_iii:nnnnN #1#2 #3#4 #5 - { ; #5 {#3}{#4} {#1}{#2} ; } % \end{macrocode} -% In the case of a \enquote{small} result, what comes after -% \cs{@@_sub_back_carry_small:wN} has between $1$ -% and $9$ digits, and is not zero. +% \end{macro} +% +% \begin{macro}[aux, EXP]{\@@_sub_back_very_far_o:wwwwNN} +% \begin{macro}[aux, EXP]{\@@_sub_back_very_far_ii_o:nnNwwNN} +% The case where $x-y$ and $x$ have the same exponent is a bit more +% tricky, mostly because it cannot reuse the same auxiliaries. Shift +% the $y$~mantissa by adding a leading~$0$. Then the logic is similar +% to the \texttt{not_far} functions above. Rounding is a bit more +% complicated: we have two \meta{rounding} digits |#3| and |#6| (from +% the decimation, and from the new shift) to take into account, and +% getting the parity of the main result requires a computation. The +% first \cs{__int_value:w} triggers the second one because the number +% is unfinished; we can thus not use $0$ in place of $2$ there. % \begin{macrocode} -\cs_new:Npn \@@_sub_back_carry_small:wN #1; +\cs_new:Npn \@@_sub_back_very_far_o:wwwwNN #1#2#3#4#5#6#7 + { + \@@_pack_eight:wNNNNNNNN + \@@_sub_back_very_far_ii_o:nnNwwNN + { 0 #1#2#3 #4#5#6#7 } + ; + } +\cs_new:Npn \@@_sub_back_very_far_ii_o:nnNwwNN #1#2 ; #3 ; #4 ~ #5; #6#7 { - - \exp_after:wN \@@_use_i_until_s:nw - \use_none:nnnnnnnnn #1 012345678; - \@@_sub_back_carry_small_ii:NNNNNNNN #1 00000000 ; + \exp_after:wN \@@_basics_pack_high:NNNNNw + \int_use:N \__int_eval:w 1#4 - #1 - \c_one + \exp_after:wN \@@_basics_pack_low:NNNNNw + \int_use:N \__int_eval:w 2#5 - #2 + - \exp_after:wN \@@_round_neg:NNN + \exp_after:wN #7 + \__int_value:w + \if_int_odd:w \__int_eval:w #5 - #2 \__int_eval_end: + 1 \else: 2 \fi: + \__int_value:w \@@_round_digit:Nw #3 #6 ; + \exp_after:wN ; } -\cs_new:Npn \@@_sub_back_carry_small_ii:NNNNNNNN #1#2#3#4 #5#6#7#8 - { \@@_sub_back_carry_small_iii:nnNwN {#1#2#3#4} {#5#6#7#8} } -\cs_new:Npn \@@_sub_back_carry_small_iii:nnNwN #1 #2 #3 #4; #5 - { ; #5 {#1} {#2} {#3000} {0000} ; } % \end{macrocode} % \end{macro} -% +% \end{macro} % % \subsection{Multiplication} % -% \begin{macro}[int, EXP]{\@@_*_o:ww} -% For multiplication, everything is easy. No need to grab the -% \meta{body_2}. -% \begin{macrocode} -\cs_new:cpn { @@_*_o:ww } - \s_@@ \@@_chk:w #1 #2 #3 ; \s_@@ \@@_chk:w #4 #5 - { \@@_mul_cases:NN #1 #4 #2 #5 #3 ; } -% \end{macrocode} -% \end{macro} -% % \subsubsection{Signs, and special numbers} % -% \begin{macro}[EXP,aux]{\@@_mul_cases:NN} -% \begin{syntax} -% \cs{@@_mul_cases:NN} \meta{case_1} \meta{case_2} -% ~~\meta{sign_1} \meta{sign_2} \meta{body_1} |;| \meta{body_2} |;| -% \end{syntax} -% Expands the following tokens on the input stream once. -% The special cases are coded at the start of this module, -% and identical to the ones for division.\footnote{Bruno: \texttt{nan} -% are not treated properly: $\infty\times 0$ should signal.} -%^^A todo: use the faster \if_meaning:w. +% \begin{macro}[int, EXP]{\@@_*_o:ww} +% We go through an auxiliary, which is common with \cs{@@_/_o:ww}. +% The first argument is the operation, used for the invalid operation +% exception. The second is inserted in a formula to dispatch cases +% slightly differently between multiplication and division. The third +% is the operation for normal floating points. The fourth is there +% for extra cases needed in \cs{@@_/_o:ww}. % \begin{macrocode} -\cs_new:Npn \@@_mul_cases:NN #1 #2 +\cs_new_nopar:cpn { @@_*_o:ww } { - \if_case:w \if_meaning:w 1 #1 #2 \else: - \if_meaning:w 1 #2 #1 \else: - \if_meaning:w #1#2 #1 \else: - \if_int_compare:w \__int_eval:w #1 + #2 > \c_two - 3 \else: 4 \fi: \fi: \fi: \fi: - \exp_stop_f: - \exp_after:wN \@@_basics_return_zero:NNww - \or: \exp_after:wN \@@_mul_normal:NNww - \or: \exp_after:wN \@@_basics_return_inf:NNww - \or: \exp_after:wN \@@_basics_return_nan:NNww - \or: - \exp_after:wN \@@_mul_invalid:NNNNww - \exp_after:wN #1 - \exp_after:wN #2 - \fi: - } -\cs_new:Npn \@@_mul_invalid:NNNNww #1#2#3#4#5; #6; - { - \@@_invalid_operation:Nnww \c_nan_fp { * } - \s_@@ \@@_chk:w #1 #3 #5 ; - \s_@@ \@@_chk:w #2 #4 #6 ; + \@@_mul_cases_o:NnNnww + * + { - \c_two + } + \@@_mul_npos_o:Nww + { } } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_mul_normal:NNww} -% \begin{syntax} -% \cs{@@_mul_normal:NNww} \meta{sign_1} \meta{sign_2} -% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;| -% \end{syntax} -% We now have two normal numbers to multiply. Combine the signs. +% \begin{macro}[int, EXP]{\@@_mul_cases_o:nNnnww} +% Split into $10$ cases ($12$ for division). +% If both numbers are normal, go to case $0$ +% (same sign) or case $1$ (opposite signs): in both cases, call +% \cs{@@_mul_npos_o:Nww} to do the work. If the first operand is +% \texttt{nan}, go to case $2$, in which the second operand is +% discarded; if the second operand is \texttt{nan}, go to case $3$, in +% which the first operand is discarded (note the weird interaction +% with the final test on signs). Then we separate the case where the +% first number is normal and the second is zero: this goes to cases +% $4$ and $5$ for multiplication, $10$ and $11$ for division. +% Otherwise, we do a computation which +% dispatches the products $0\times 0 = 0\times 1 = 1\times 0 = 0$ to +% case $4$ or $5$ depending on the combined sign, the products +% $0\times\infty$ and $\infty\times0$ to case $6$ or $7$ (invalid +% operation), and the products $1\times\infty = \infty\times1 = +% \infty\times\infty = \infty$ to cases $8$ and $9$. Note that the +% code for these two cases (which return $\pm\infty$) is inserted as +% argument |#4|, because it differs in the case of divisions. % \begin{macrocode} -\cs_new:Npn \@@_mul_normal:NNww #1#2 +\cs_new:Npn \@@_mul_cases_o:NnNnww + #1#2#3#4 \s_@@ \@@_chk:w #5#6#7; \s_@@ \@@_chk:w #8#9 { - \if:w #1#2 - \exp_after:wN \@@_mul_npos:Nnwnw - \exp_after:wN 0 - \else: - \exp_after:wN \@@_mul_npos:Nnwnw - \exp_after:wN 2 + \if_case:w \__int_eval:w + \if_int_compare:w #5 #8 = \c_eleven + \c_one + \else: + \if_meaning:w 3 #8 + \c_three + \else: + \if_meaning:w 3 #5 + \c_two + \else: + \if_int_compare:w #5 #8 = \c_ten + \c_nine #2 - \c_two + \else: + (#5 #2 #8) / \c_two * \c_two + \c_seven + \fi: + \fi: + \fi: + \fi: + \if_meaning:w #6 #9 - \c_one \fi: + \__int_eval_end: + \@@_case_use:nw { #3 0 } + \or: \@@_case_use:nw { #3 2 } + \or: \@@_case_return_i_o:ww + \or: \@@_case_return_ii_o:ww + \or: \@@_case_return_o:Nww \c_zero_fp + \or: \@@_case_return_o:Nww \c_minus_zero_fp + \or: \@@_case_use:nw { \@@_invalid_operation_o:Nww #1 } + \or: \@@_case_use:nw { \@@_invalid_operation_o:Nww #1 } + \or: \@@_case_return_o:Nww \c_inf_fp + \or: \@@_case_return_o:Nww \c_minus_inf_fp + #4 \fi: + \s_@@ \@@_chk:w #5 #6 #7; + \s_@@ \@@_chk:w #8 #9 } % \end{macrocode} % \end{macro} @@ -821,39 +860,44 @@ % In this subsection, we perform the multiplication % of two positive normal numbers. % -% \begin{macro}[EXP]{\@@_mul_npos:Nnwnw} -% \begin{syntax} -% \cs{@@_mul_npos:Nnwnw} \meta{sign} -% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;| -% \end{syntax} -% As for addition, \meta{sign} is the final sign. After the computation, -% \cs{@@_sanitize:Nw} checks for overflow or underflow. -% As before, \cs{__int_eval:w} computes the exponent, catching any -% shift coming from the computation in the mantissa. Again, the -% \meta{sign} is needed for rounding to be done properly, so we move -% it around with us. We setup the post-expansion here, triggered by -% \cs{@@_mul_mantissa:nnnnNnnnn}. +% \begin{macro}[int, EXP]{\@@_mul_npos_o:Nww} +% \begin{quote} +% \cs{@@_mul_npos_o:Nww} \meta{final sign} +% \cs{s_@@} \cs{@@_chk:w} |1| \meta{sign_1} \Arg{exp_1} \meta{body_1} |;| +% \cs{s_@@} \cs{@@_chk:w} |1| \meta{sign_2} \Arg{exp_2} \meta{body_2} |;| +% \end{quote} +% After the computation, \cs{@@_sanitize:Nw} checks for overflow or +% underflow. As we did for addition, \cs{__int_eval:w} computes the +% exponent, catching any shift coming from the computation in the +% mantissa. The \meta{final sign} is needed to do the rounding +% properly in the mantissa computation. We setup the post-expansion +% here, triggered by \cs{@@_mul_mantissa_o:nnnnNnnnn}. % \begin{macrocode} -\cs_new:Npn \@@_mul_npos:Nnwnw #1 #2#3; #4 #5; +\cs_new:Npn \@@_mul_npos_o:Nww + #1 \s_@@ \@@_chk:w #2 #3 #4 #5 ; \s_@@ \@@_chk:w #6 #7 #8 #9 ; { \exp_after:wN \@@_sanitize:Nw \exp_after:wN #1 \int_use:N \__int_eval:w - #2 + #4 - \@@_mul_mantissa:nnnnNnnnn #3 #1 #5 - \exp_after:wN ; + #4 + #8 + \@@_mul_mantissa_o:nnnnNnnnn #5 #1 #9 } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_mul_mantissa:nnnnNnnnn} -% \begin{syntax} -% \cs{@@_mul_mantissa:nnnnNnnnn} -% ~~\Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \meta{sign} -% ~~\Arg{Y_1} \Arg{Y_2} \Arg{Y_3} \Arg{Y_4} \meta{;} -% \end{syntax} -% After one expansion, the token following \meta{Y_4} must be a semicolon -% (represented by \meta{;}). +% \begin{macro}[aux, rEXP]{\@@_mul_mantissa_o:nnnnNnnnn} +% \begin{macro}[aux, EXP] +% {\@@_mul_mantissa_drop:NNNNNw, \@@_mul_mantissa_keep:NNNNNw} +% \begin{quote} +% \cs{@@_mul_mantissa_o:nnnnNnnnn} +% \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \meta{sign} +% \Arg{Y_1} \Arg{Y_2} \Arg{Y_3} \Arg{Y_4} +% \end{quote} +% Note the three semicolons at the end of the definition. One is for +% the last \cs{@@_mul_mantissa_drop:NNNNNw}; one is for +% \cs{@@_round_digit:Nw} later on; and one, preceeded by +% \cs{exp_after:wN}, which is correctly expanded (within an +% \cs{__int_eval:w}), is used by \cs{@@_basics_pack_low:NNNNNw}. % % The product of two $16$ digit integers has $31$ or $32$ digits, % but it is impossible to know which one before computing. The place @@ -865,9 +909,9 @@ % known, and we can do the rounding within yet another set of % \cs{__int_eval:w}. % \begin{macrocode} -\cs_new:Npn \@@_mul_mantissa:nnnnNnnnn #1#2#3#4 #5 #6#7#8#9 +\cs_new:Npn \@@_mul_mantissa_o:nnnnNnnnn #1#2#3#4 #5 #6#7#8#9 { - \exp_after:wN \@@_mul_mantissa_after:NNN + \exp_after:wN \@@_mul_mantissa_test_f:NNN \exp_after:wN #5 \int_use:N \__int_eval:w 99990000 + #1*#6 + \exp_after:wN \@@_mul_mantissa_keep:NNNNNw @@ -881,688 +925,641 @@ \exp_after:wN \@@_mul_mantissa_drop:NNNNNw \int_use:N \__int_eval:w 99990000 + #3*#9 + #4*#8 + \exp_after:wN \@@_mul_mantissa_drop:NNNNNw - \int_use:N \__int_eval:w 100000000 + #4*#9 \exp_after:wN ; + \int_use:N \__int_eval:w 100000000 + #4*#9 ; + ; \exp_after:wN ; } \cs_new:Npn \@@_mul_mantissa_drop:NNNNNw #1#2#3#4#5 #6; { #1#2#3#4#5 ; + #6 } \cs_new:Npn \@@_mul_mantissa_keep:NNNNNw #1#2#3#4#5 #6; { #1#2#3#4#5 ; #6 ; } % \end{macrocode} -% Once the first \cs{int_use:N} \cs{__int_eval:w}, and all the -% \cs{@@_mul_mantissa_...:NNNNNw} have been expanded, -% we get +% \end{macro} +% \end{macro} +% +% \begin{macro}[aux, rEXP]{\@@_mul_mantissa_test_f:NNN} % \begin{quote} -% \cs{@@_mul_mantissa_after:NNN} \meta{sign} |1| -% ~~\meta{digits 1--8} |;| \meta{digits 9--12} |;| \meta{digits 13--16} |;| -% ~~|+| \meta{digits 17--20} |+| \meta{digits 21--24} -% ~~|+| \meta{digits 25--28} |+| \meta{digits 29--32} |;| +% \cs{@@_mul_mantissa_test_f:NNN} \meta{sign} |1| +% \meta{digits 1--8} |;| \meta{digits 9--12} |;| \meta{digits 13--16} |;| +% |+| \meta{digits 17--20} |+| \meta{digits 21--24} +% |+| \meta{digits 25--28} |+| \meta{digits 29--32} |;| +% \cs{exp_after:wN} |;| % \end{quote} % If the \meta{digit 1} is non-zero, then for rounding we only care -% about the digits $16$ and $17$, and whether all other digits are zero +% about the digits $16$ and $17$, and whether further digits are zero % or not (check for exact ties). On the other hand, if \meta{digit 1} -% is zero, we care about digits $17$ and $18$, and whether all others are -% zero. +% is zero, we care about digits $17$ and $18$, and whether further +% digits are zero. % \begin{macrocode} -\cs_new:Npn \@@_mul_mantissa_after:NNN #1 #2 #3 +\cs_new:Npn \@@_mul_mantissa_test_f:NNN #1 #2 #3 { - \if:w 0 #3 - \exp_after:wN \@@_mul_mantissa_small:NNwwwN + \if_meaning:w 0 #3 + \exp_after:wN \@@_mul_mantissa_small_f:NNwwwN \else: - \exp_after:wN \@@_mul_mantissa_large:NwwNNNN + \exp_after:wN \@@_mul_mantissa_large_f:NwwNNNN \fi: #1 #3 } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_mul_mantissa_large:NwwNNNN} +% \begin{macro}[aux, EXP]{\@@_mul_mantissa_large_f:NwwNNNN} % In this branch, \meta{digit 1} is non-zero. The result is thus % \meta{digits 1--16}, plus some rounding which depends on the digits % $16$, $17$, and whether all subsequent digits are zero or not. -% Here, \cs{@@_round_s:NNNw} takes the \meta{sign}, followed by -% digits $16$, $17$, and an integer expression which is zero if and -% only if all further digits are zero. +% Here, \cs{@@_round_digit:Nw} takes digits $17$ and further (as an +% integer expression), and replaces it by a \meta{rounding digit}, +% suitable for \cs{@@_round:NNN}. % \begin{macrocode} -\cs_new:Npn \@@_mul_mantissa_large:NwwNNNN #1 #2; #3; #4#5#6#7; + +\cs_new:Npn \@@_mul_mantissa_large_f:NwwNNNN #1 #2; #3; #4#5#6#7; + { \exp_after:wN \@@_basics_pack_high:NNNNNw \int_use:N \__int_eval:w 1#2 \exp_after:wN \@@_basics_pack_low:NNNNNw - \int_use:N \__int_eval:w 1#3#4#5#6#7 + \@@_round_s:NNNw #1 #7 + \int_use:N \__int_eval:w 1#3#4#5#6#7 + + \exp_after:wN \@@_round:NNN + \exp_after:wN #1 + \exp_after:wN #7 + \__int_value:w \@@_round_digit:Nw } % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_mul_mantissa_small:NNwwwN} +% \begin{macro}[aux, rEXP]{\@@_mul_mantissa_small_f:NNwwwN} % In this branch, \meta{digit 1} is zero. Our result will thus be % \meta{digits 2--17}, plus some rounding which depends on the digits % $17$, $18$, and whether all subsequent digits are zero or not. % The $8$ digits |1#3| are followed, after expansion of the % \texttt{small_pack} auxiliary, by the next digit, to form a $9$ -% digit number. Also, rounding may have caused a carry, which is -% then converted to \cs{c_ten} rather than the usual \cs{c_one}, -% because of the shift. +% digit number. % \begin{macrocode} -\cs_new:Npn \@@_mul_mantissa_small:NNwwwN #1 #2#3; #4; #5; + #6 +\cs_new:Npn \@@_mul_mantissa_small_f:NNwwwN #1 #2#3; #4#5; #6; + #7 { - \c_one \exp_after:wN \@@_basics_pack_high:NNNNNw - \int_use:N \__int_eval:w 1#3 - \exp_after:wN \@@_mul_mantissa_small_pack:NNNNNNw - \int_use:N \__int_eval:w 1#4#5#6 + \@@_round_s:NNNw #1 #6 - } -\cs_new:Npn \@@_mul_mantissa_small_pack:NNNNNNw #1#2 #3#4#5#6 #7; - { - #2 - \if:w 2 #1 - + \c_ten - \fi: - ; {#3#4#5#6} {#7} ; + \int_use:N \__int_eval:w 1#3#4 + \exp_after:wN \@@_basics_pack_low:NNNNNw + \int_use:N \__int_eval:w 1#5#6#7 + + \exp_after:wN \@@_round:NNN + \exp_after:wN #1 + \exp_after:wN #7 + \__int_value:w \@@_round_digit:Nw } % \end{macrocode} % \end{macro} % % \subsection{Division} % -% Time is now ripe to tackle the hardest of the four elementary -% operations: division. -% -% \begin{macro}[EXP]{\@@_/_o:ww} -% For division we swap the two floating point numbers. -% \begin{macrocode} -\cs_new:cpn { @@_/_o:ww } - \s_@@ \@@_chk:w #1 #2 #3 ; \s_@@ \@@_chk:w #4 #5 #6 ; - { \@@_div_back_cases:NN #4 #1 #5 #2 #6 ; #3 ; } -% \end{macrocode} -% \end{macro} -% % \subsubsection{Signs, and special numbers} % -% In the case of division, the order of the operands matters, -% and it turns out to be slightly simpler if we internally -% compute the \enquote{backwards} division. -% -% \begin{macro}[EXP,aux]{\@@_div_back_cases:NN} -% \begin{syntax} -% \cs{@@_div_back_cases:NN} \meta{case_2} \meta{case_1} -% ~~\meta{sign_2} \meta{sign_1} \meta{body_2} |;| \meta{body_1} |;| -% \end{syntax} -% Expands the following tokens on the input stream once. -% \begin{macrocode} -\cs_new:Npn \@@_div_back_cases:NN #1 #2 - { - \if_case:w \if_int_compare:w #1 = #2 \exp_stop_f: - #1 \exp_stop_f: - \else: - \if_int_compare:w #1 < #2 \exp_stop_f: - \if:w 3 #2 \c_four \else: \c_five \fi: - \else: - \if:w 3 #1 \c_six \else: \c_seven \fi: - \fi: - \fi: - \exp_after:wN \@@_div_back_invalid:NNNww \exp_after:wN 0 - \or: \exp_after:wN \@@_div_back_normal:NNww - \or: \exp_after:wN \@@_div_back_invalid:NNNww \exp_after:wN 2 - \or: \exp_after:wN \@@_basics_return_nan_nan:NNww - \or: - \exp_after:wN \@@_basics_return_ii:NNNNww - \exp_after:wN #1 - \exp_after:wN #2 - \or: \exp_after:wN \@@_basics_return_inf:NNww - \or: - \exp_after:wN \@@_basics_return_i:NNNNww - \exp_after:wN #1 - \exp_after:wN #2 - \or: \exp_after:wN \@@_basics_return_zero:NNww - \fi: - } -% \end{macrocode} -% Most of the special cases are common with some -% previous operations. We only need to write the cases of -% $0/0$ and $\infty/\infty$. -% \begin{macrocode} -\cs_new:Npn \@@_div_back_invalid:NNNww #1#2#3 #4; #5; - { - \@@_invalid_operation:Nnww \c_nan_fp { / } - \s_@@ \@@_chk:w #1 #3 #5 ; - \s_@@ \@@_chk:w #1 #2 #4 ; - } -% \end{macrocode} -% \end{macro} +% Time is now ripe to tackle the hardest of the four elementary +% operations: division. % -% \begin{macro}{\@@_div_back_normal:NNww} -% \begin{syntax} -% \cs{@@_div_back_normal:NNww} \meta{sign_1} \meta{sign_2} -% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;| -% \end{syntax} -% We now have two normal numbers to divide. Combine the signs. +% \begin{macro}[int, EXP]{\@@_/_o:ww} +% Filtering special floating point is very similar to what we did for +% multiplications, with a few variations. Invalid operation +% exceptions display |/| rather than |*|. In the formula for +% dispatch, we replace |- \c_two +| by |-|. The case of normal +% numbers is treated using \cs{@@_div_npos_o:Nww} rather than +% \cs{@@_mul_npos_o:Nww}. There are two additionnal cases: if the +% first operand is normal and the second is a zero, then the division +% by zero exception is raised: cases $10$ and $11$ of the +% \cs{if_case:w} construction in \cs{@@_mul_cases_o:NnNnww} are +% provided as the fourth argument here. % \begin{macrocode} -\cs_new:Npn \@@_div_back_normal:NNww #1#2 +\cs_new_nopar:cpn { @@_/_o:ww } { - \if:w #1#2 - \exp_after:wN \@@_div_back_npos:Nnwnw - \exp_after:wN 0 - \else: - \exp_after:wN \@@_div_back_npos:Nnwnw - \exp_after:wN 2 - \fi: + \@@_mul_cases_o:NnNnww + / + { - } + \@@_div_npos_o:Nww + { + \or: + \@@_case_use:nw + { \@@_division_by_zero_o:NNww \c_inf_fp / } + \or: + \@@_case_use:nw + { \@@_division_by_zero_o:NNww \c_minus_inf_fp / } + } } % \end{macrocode} % \end{macro} % -% \subsubsection{Absolute (backwards) division} -% -% In this subsection, we perform the division -% of two positive normal numbers. -% -% \begin{macro}[EXP]{\@@_div_back_npos:Nnwnw} -% \begin{syntax} -% \cs{@@_div_back_npos:Nnwnw} \meta{sign} -% ~~\Arg{exp Z} \Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} |;| -% ~~\Arg{exp A} \Arg{A_1} \Arg{A_2} \Arg{A_3} \Arg{A_4} |;| -% \end{syntax} -% We want to compute $A/Z$. As for addition and multiplication, -% \meta{sign} is the final sign. Checking for underflow and -% overflow is done using the same auxiliary as for multiplication. -% As explained just below, we first compute $y$, which is -% the $5$ first digits of $Z$, plus $1$, and then compute pieces -% of the quotient roughly $4$ digits at a time. Here, |#1| is -% a single digit, |#2| and |#7| are the exponents (integers), -% |#8| is three brace groups, and all others are each $4$ digits. +% \begin{macro}[aux, EXP]{\@@_div_npos_o:Nww} +% \begin{quote} +% \cs{@@_div_npos_o:Nww} \meta{final sign} +% \cs{s_@@} \cs{@@_chk:w} |1| \meta{sign_A} \Arg{exp A} +% \Arg{A_1} \Arg{A_2} \Arg{A_3} \Arg{A_4} |;| +% \cs{s_@@} \cs{@@_chk:w} |1| \meta{sign_Z} \Arg{exp Z} +% \Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} |;| +% \end{quote} +% We want to compute $A/Z$. As for multiplication, +% \cs{@@_sanitize:Nw} checks for overflow or underflow; we provide it +% with the \meta{final sign}, and an integer expression in which we +% compute the exponent. We set up the arguments of +% \cs{@@_div_mantissa_i_o:wnnw}, namely an integer \meta{y} obtained +% by adding $1$ to the first $5$ digits of $Z$ (explanation given soon +% below), then the four \Arg{A_{i}}, then the four \Arg{Z_{i}}, a +% semi-colon, and the \meta{final sign}, used for rounding at the end. % \begin{macrocode} -\cs_new:Npn \@@_div_back_npos:Nnwnw #1 #2 #3#4#5#6; #7 #8; +\cs_new:Npn \@@_div_npos_o:Nww + #1 \s_@@ \@@_chk:w 1 #2 #3 #4 ; \s_@@ \@@_chk:w 1 #5 #6 #7#8#9; { \exp_after:wN \@@_sanitize:Nw \exp_after:wN #1 \int_use:N \__int_eval:w - #7 - #2 - \@@_div_mantissa_i:wNwnn #3; #4; - #8 {#3}{#4}{#5}{#6} #1 + #3 - #6 + \exp_after:wN \@@_div_mantissa_i_o:wnnw + \int_use:N \__int_eval:w #7 \use_i:nnnn #8 + \c_one ; + #4 + {#7}{#8}#9 ; + #1 } % \end{macrocode} % \end{macro} % -% We are given two numbers, $A=0.A_{1}A_{2}A_{3}A_{4}$ -% and $Z=0.Z_{1}Z_{2}Z_{3}Z_{4}$, in blocks of $4$ digits, -% and we know that the first digits of $A_{1}$ and of $Z_{1}$ -% are non-zero. To compute $A/Z$, we proceed as follows. -% \begin{itemize} -% \item Find an integer $Q_{1} \simeq 10^4 A / Z$. -% \item Replace $A$ by $B = 10^4 A - Q_{1} Z$. -% \item Find an integer $Q_{2} \simeq 10^4 B / Z$. -% \item Replace $B$ by $C = 10^4 B - Q_{2} Z$. -% \item Find an integer $Q_{3} \simeq 10^4 C / Z$. -% \item Replace $C$ by $D = 10^4 C - Q_{3} Z$. -% \item Find an integer $Q_{4} \simeq 10^4 D / Z$. -% \item Consider $E = 10^4 D - Q_{4} Z$, and ensure +% \subsubsection{Work plan} +% +% In this subsection, we explain how to avoid overflowing \TeX{}'s +% integers when performing the division of two positive normal numbers. +% +% We are given two numbers, $A=0.A_{1}A_{2}A_{3}A_{4}$ and +% $Z=0.Z_{1}Z_{2}Z_{3}Z_{4}$, in blocks of $4$ digits, and we know that +% the first digits of $A_{1}$ and of $Z_{1}$ are non-zero. To compute +% $A/Z$, we proceed as follows. +% \begin{itemize} +% \item Find an integer $Q_{A} \simeq 10^{4} A / Z$. +% \item Replace $A$ by $B = 10^{4} A - Q_{A} Z$. +% \item Find an integer $Q_{B} \simeq 10^{4} B / Z$. +% \item Replace $B$ by $C = 10^{4} B - Q_{B} Z$. +% \item Find an integer $Q_{C} \simeq 10^{4} C / Z$. +% \item Replace $C$ by $D = 10^{4} C - Q_{C} Z$. +% \item Find an integer $Q_{D} \simeq 10^{4} D / Z$. +% \item Consider $E = 10^{4} D - Q_{D} Z$, and ensure % correct rounding. -% \end{itemize} -% The calculations of $B$, $C$, $D$, and $E$ can be done -% exactly with only $16$ (or $17$) digits. -% -% Unfortunately, things are not as easy as they seem. -% Firstly, we make sure that all intermediate steps are positive, -% since negative results would require extra calculations at the end. -% This requires that $Q_{1} \leq 10^4 A / Z$ etc. A reasonable -% attempt would be to define $Q_{1}$ as -% \[ +% \end{itemize} +% The result is then $Q = 10^{-4} Q_{A} + 10^{-8} Q_{B} + 10^{-12} Q_{C} +% + 10^{-16} Q_{D} + \text{rounding}$. Since the $Q_{i}$ are integers, +% $B$, $C$, $D$, and~$E$ are all exact multiples of $10^{-16}$, in other +% words, computing with $16$ digits after the decimal separator yields +% exact results. The problem will be overflow: in general $B$, $C$, +% $D$, and $E$ may be greater than $1$. +% +% Unfortunately, things are not as easy as they seem. In particular, we +% want all intermediate steps to be positive, since negative results +% would require extra calculations at the end. This requires that +% $Q_{A} \leq 10^{4} A / Z$ \emph{etc.} A reasonable attempt would be +% to define $Q_{A}$ as +% \begin{equation*} % \cs{int_eval:n} \left\{ -% \frac{ A_{1} A_{2} }{ Z_{1} + 1 } - 1 \right\}. -% \] -% Subtracting $1$ at the end takes care of the fact that e\TeX{}'s -% \cs{__int_eval:w} rounds instead of truncating. We add $1$ to $Z_{1}$ -% because $ Z_{1} \leq 10^4 Z < Z_{1}+1$ and we need $Q_{1}$ -% to be an underestimate. However, we are now underestimating -% $Q_{1}$ too much: it can be wrong by up to $100$, for instance -% when $Z = 0.1$ and $A \simeq 1$. Then $B$ could take values up to -% $10$ (maybe more), and a few steps down the line, we would run into -% arithmetic overflow, since \TeX{} can only handle integers less than -% roughly $2\cdot 10^9$. -% -% A better formula is to take -% \[ -% Q_{1} = \cs{int_eval:n} \left\{ +% \frac{ A_{1} A_{2} }{ Z_{1} + 1 } - 1 \right\} +% \leq 10^{4} \frac{A}{Z} +% \end{equation*} +% Subtracting $1$ at the end takes care of the fact that \eTeX{}'s +% \cs{__int_eval:w} rounds divisions instead of truncating (really, +% $1/2$ would be sufficient, but we work with integers). We add $1$ to +% $Z_{1}$ because $Z_{1} \leq 10^{4}Z < Z_{1}+1$ and we need $Q_{A}$ to +% be an underestimate. However, we are now underestimating $Q_{A}$ too +% much: it can be wrong by up to $100$, for instance when $Z = 0.1$ and +% $A \simeq 1$. Then $B$ could take values up to $10$ (maybe more), and +% a few steps down the line, we would run into arithmetic overflow, +% since \TeX{} can only handle integers less than roughly $2\cdot +% 10^{9}$. +% +% A better formula is to take +% \begin{equation*} +% Q_{A} = \cs{int_eval:n} \left\{ % \frac{ 10 \cdot A_{1} A_{2} } % { \left\lfloor 10^{-3} \cdot Z_{1} Z_{2} \right\rfloor + 1 } % - 1 \right\}. -% \] -% This is always less than $10^9 A / (10^5 Z)$, as we wanted. -% In words, we take the $5$ first digits of $Z$ into account, -% and the $8$ first digits of $A$, using $0$ as a $9$-th digit -% rather than the true digit for efficiency reasons. We shall -% prove that using this formula to define all the $Q_{i}$ -% leads to no overflow. For convenience, let us denote -% \[ +% \end{equation*} +% This is always less than $10^{9} A / (10^{5} Z)$, as we wanted. In +% words, we take the $5$ first digits of $Z$ into account, and the $8$ +% first digits of $A$, using $0$ as a $9$-th digit rather than the true +% digit for efficiency reasons. We shall prove that using this formula +% to define all the $Q_{i}$ avoids any overflow. For convenience, let +% us denote +% \begin{equation*} % y = \left\lfloor 10^{-3} \cdot Z_{1} Z_{2} \right\rfloor + 1, -% \] -% so that, taking into account the fact that e\TeX{} rounds ties -% away from zero, -% \[ -% Q_{1} = \left\lfloor A_{1}A_{2}0/y - 1/2 \right\rfloor. -% \] -% Note that $10^4<y\leq 10^5$, and $999 \leq Q_{1} \leq 99989$. -% Also note that this formula does not cause an overflow as long as -% $A<2.147\cdots$, since the numerator involves an integer slightly -% smaller than $10^9A$. -% -% Let us bound $B$: -% \begin{align*} -% 10^5 B +% \end{equation*} +% so that, taking into account the fact that \eTeX{} rounds ties away +% from zero, +% \begin{align*} +% Q_{A} +% &= \left\lfloor \frac{A_{1}A_{2}0}{y} - \frac{1}{2} \right\rfloor +% \\ +% &>\frac{A_{1}A_{2}0}{y} - \frac{3}{2}. +% \end{align*} +% Note that $10^{4}<y\leq 10^{5}$, and $999 \leq Q_{A} \leq 99989$. +% Also note that this formula does not cause an overflow as long as $A < +% (2^{31}-1) / 10^{9} \simeq 2.147\cdots$, since the numerator involves an +% integer slightly smaller than $10^{9} A$. +% +% Let us bound $B$: +% \begin{align*} +% 10^{5} B % &= % A_{1}A_{2}0 + 10 \cdot 0.A_{3}A_{4} -% - 10 \cdot Z_{1}.Z_{2}Z_{3}Z_{4} -% \cdot \left\lfloor A_{1}A_{2}0/y - 1/2 \right\rfloor +% - 10 \cdot Z_{1}.Z_{2}Z_{3}Z_{4} \cdot Q_{A} % \\ % &< % A_{1}A_{2}0 -% \cdot \left( 1 - 10 \frac{Z_{1}.Z_{2}Z_{3}Z_{4}}{y} \right) +% \cdot \left( 1 - 10 \cdot \frac{Z_{1}.Z_{2}Z_{3}Z_{4}}{y} \right) % + \frac{3}{2} \cdot 10 \cdot Z_{1}.Z_{2}Z_{3}Z_{4} + 10 % \\ % &\leq -% \frac{A_{1}A_{2}0 \cdot (y - 10 Z_{1}.Z_{2}Z_{3}Z_{4})}{y} +% \frac{A_{1}A_{2}0 \cdot (y - 10 \cdot Z_{1}.Z_{2}Z_{3}Z_{4})}{y} % + \frac{3}{2} y + 10 % \\ % &\leq -% \frac{A_{1}A_{2}0}{y} + \frac{3}{2} y + 10 +% \frac{A_{1}A_{2}0\cdot 1}{y} + \frac{3}{2} y + 10 % \leq -% \frac{10^9 A}{y} + 1.6 y -% \end{align*} -% At the last step, we hide $10$ into the second term -% for later convenience. The same reasoning yields\footnote{Bruno: -% I need to find much better notations. These are not great.} -% \begin{align*} -% 10^5 B &< 10^9 A/y + 1.6 y, \\ -% 10^5 C &< 10^9 B/y + 1.6 y, \\ -% 10^5 D &< 10^9 C/y + 1.6 y, \\ -% 10^5 E &< 10^9 D/y + 1.6 y. \\ -% \end{align*} -% The goal is now to prove that none of $B$, $C$, $D$, and $E$ -% can go beyond $2.147\cdots$. Simply bounding each term on the -% right-hand side separately will not be tight enough: for instance, -% we would get $10^5 B < 10^5 + 1.6\cdot 10^5 = 2.6 \cdot 10^5$, -% which is too large. -% -% Combining the various inequalities together with $A<1$, we get -% \begin{align*} -% 10^5 B &< 10^9/y + 1.6 y, \\ -% 10^5 C &< 10^{13}/y^2 + 1.6 (y + 10^4), \\ -% 10^5 D &< 10^{17}/y^3 + 1.6 (y + 10^4 + 10^8/y), \\ -% 10^5 E &< 10^{21}/y^4 + 1.6 (y + 10^4 + 10^8/y + 10^{12}/y^2). \\ -% \end{align*} -% All of those bounds are convex functions of $y$ (since every power -% of $y$ involved is convex, and hte coefficients are positive), and -% thus maximal at one of the end-points of the allowed range -% $10^4<y\leq 10^5$. Thus, -% \begin{align*} -% 10^5 B &< \mathrm{max} ( 1.16\cdot 10^5, 1.7 \cdot 10^5), \\ -% 10^5 C &< \mathrm{max} ( 1.32\cdot 10^5, 1.77 \cdot 10^5), \\ -% 10^5 D &< \mathrm{max} ( 1.48\cdot 10^5, 1.777 \cdot 10^5), \\ -% 10^5 E &< \mathrm{max} ( 1.64\cdot 10^5, 1.7777 \cdot 10^5). \\ -% \end{align*} -% All of those bounds are less than $2.147\cdot 10^5$, and -% we are thus within \TeX{}'s bounds in all cases!\footnote{Bruno: -% but I need to check this very carefully again.} -% -% We will later need to have a bound on the $Q_{i}$. Their -% definitions imply that $Q_{1} < 10^9 A/y - 1/2 < 10^5 A$ and -% similarly for the other $Q_{i}$. Thus each of them is at most -% $177770$. -% -% The last step is to ensure correct rounding. We have -% \[ -% A/Z = \sum_{i=1}^4 \left(10^{-4i} Q_{i}\right) + 10^{-16} E/Z -% \] -% exactly. Furthermore, we know that the result will be between -% $0.1$ (inclusive) and $10$, so we only need to know the integer -% part of $E/Z$, and a \enquote{rounding} digit encoding the rest -% (see maybe addition for an explanation of why). Equivalently, -% we need to find the integer part of $2E/Z$, and determine whether -% it was an exact integer or not (this serves to detect ties). Since -% \[ -% \frac{2E}{Z} = 2\frac{10^5 E}{10^5 Z} -% \leq 2\frac{10^5 E}{10^4} < 36, -% \] -% this integer part is between $0$ and $35$ inclusive. We let -% e\TeX{} round -% \[ +% \frac{10^{9} A}{y} + 1.6\cdot y. +% \end{align*} +% At the last step, we hide $10$ into the second term for later +% convenience. The same reasoning yields +% \begin{align*} +% 10^{5} B &< 10^{9} A/y + 1.6 y, \\ +% 10^{5} C &< 10^{9} B/y + 1.6 y, \\ +% 10^{5} D &< 10^{9} C/y + 1.6 y, \\ +% 10^{5} E &< 10^{9} D/y + 1.6 y. \\ +% \end{align*} +% The goal is now to prove that none of $B$, $C$, $D$, and $E$ can go +% beyond $(2^{31}-1) / 10^{9} = 2.147\cdots$. +% +% Combining the various inequalities together with $A<1$, we get +% \begin{align*} +% 10^{5} B &< 10^{9}/y + 1.6 y, \\ +% 10^{5} C &< 10^{13}/y^{2} + 1.6 (y + 10^{4}), \\ +% 10^{5} D &< 10^{17}/y^{3} + 1.6 (y + 10^{4} + 10^{8}/y), \\ +% 10^{5} E &< 10^{21}/y^{4} + 1.6 (y + 10^{4} + 10^{8}/y + 10^{12}/y^{2}). \\ +% \end{align*} +% All of those bounds are convex functions of $y$ (since every power of +% $y$ involved is convex, and the coefficients are positive), and thus +% maximal at one of the end-points of the allowed range $10^{4} < y \leq +% 10^{5}$. Thus, +% \begin{align*} +% 10^{5} B &< \mathrm{max} ( 1.16\cdot 10^{5}, 1.7 \cdot 10^{5}), \\ +% 10^{5} C &< \mathrm{max} ( 1.32\cdot 10^{5}, 1.77 \cdot 10^{5}), \\ +% 10^{5} D &< \mathrm{max} ( 1.48\cdot 10^{5}, 1.777 \cdot 10^{5}), \\ +% 10^{5} E &< \mathrm{max} ( 1.64\cdot 10^{5}, 1.7777 \cdot 10^{5}). \\ +% \end{align*} +% All of those bounds are less than $2.147\cdot 10^{5}$, and we are thus +% within \TeX{}'s bounds in all cases! +% +% We will later need to have a bound on the $Q_{i}$. Their definitions +% imply that $Q_{A} < 10^{9} A/y - 1/2 < 10^{5} A$ and similarly for the +% other $Q_{i}$. Thus, all of them are less than $177770$. +% +% The last step is to ensure correct rounding. We have +% \begin{equation*} +% A/Z = \sum_{i=1}^{4} \left(10^{-4i} Q_{i}\right) + 10^{-16} E/Z +% \end{equation*} +% exactly. Furthermore, we know that the result will be in $[0.1,10)$, +% hence will be rounded to a multiple of $10^{-16}$ or of $10^{-15}$, so +% we only need to know the integer part of $E/Z$, and a +% \enquote{rounding} digit encoding the rest. Equivalently, we need to +% find the integer part of $2E/Z$, and determine whether it was an +% exact integer or not (this serves to detect ties). Since +% \begin{equation*} +% \frac{2E}{Z} = 2\frac{10^{5} E}{10^{5} Z} +% \leq 2\frac{10^{5} E}{10^{4}} < 36, +% \end{equation*} +% this integer part is between $0$ and $35$ inclusive. We let \eTeX{} +% round +% \begin{equation*} % P = \cs{int_eval:n} \left\{ -% 2 \frac{E_{1}E_{2}}{Z_{1}Z_{2}} \right\}, -% \] -% which differs from $2E/Z$ by at most -% \[ +% \frac{2\cdot E_{1}E_{2}}{Z_{1}Z_{2}} \right\}, +% \end{equation*} +% which differs from $2E/Z$ by at most +% \begin{equation*} % \frac{1}{2} % + 2 \left\lvert \frac{E}{Z} - \frac{E}{10^{-8} Z_{1}Z_{2}}\right\rvert -% + 2 \left\lvert \frac{10^8 E - E_{1}E_{2}}{Z_{1}Z_{2}}\right\rvert +% + 2 \left\lvert \frac{10^{8} E - E_{1}E_{2}}{Z_{1}Z_{2}}\right\rvert % < 1, -% \] -% ($1/2$ comes from e\TeX{}'s rounding) because each absolute value -% is less than $10^{-7}$. Thus $P$ is either the correct integer part, -% or an overestimate by $1$ (impossible if $2E/Z$ is an integer). It -% then suffices to compare $PZ$ with $2E$ to get the integer part of -% $2E/Z$ and the information of whether it was an exact quotient or not. -% -% \begin{macro}[EXP]{\@@_div_mantissa_i:wNwnn} -% \begin{syntax} -% \cs{@@_div_mantissa_i:wNwnn} -% ~~\meta{Z_1} |;| \meta{Z_2} |;| -% ~~\Arg{A_1} \Arg{A_2} \Arg{A_3} \Arg{A_4} -% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign} -% \end{syntax} -% First compute $y$ from the first $5$ digits of $Z$, and -% unbrace \meta{A_1} and \meta{A_2}. -% \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_i:wNwnn #1; #2 #3; #4 #5 - { - \exp_after:wN \@@_div_mantissa_ii:ww - \int_use:N \__int_eval:w #1#2 + \c_one ; - #4 #5 ; - } -% \end{macrocode} +% \end{equation*} +% ($1/2$ comes from \eTeX{}'s rounding) because each absolute value is +% less than $10^{-7}$. Thus $P$ is either the correct integer part, or +% is off by $1$; furthermore, if $2 E / Z$ is an integer, $P = 2 E / Z$. +% We will check the sign of $2 E - P Z$. If it is negative, then $E / Z +% \in \big((P - 1) / 2, P / 2\big)$. If it is zero, then $E / Z = P / +% 2$. If it is positive, then $E / Z \in \big(P / 2, (P - 1) / 2\big)$. +% In each case, we know how to round to an integer, depending on the +% parity of $P$, and the rounding mode. +% +% \subsubsection{Implementing the mantissa division} +% +% \begin{macro}[aux, rEXP]{\@@_div_mantissa_i_o:wnnw} % \begin{quote} -% \cs{@@_div_mantissa_ii:ww} -% ~~\meta{y} |;| \meta{A_1} \meta{A_2} |;| \Arg{A_3} \Arg{A_4} -% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign} +% \cs{@@_div_mantissa_i_o:wnnw} \meta{y} |;| +% \Arg{A_1} \Arg{A_2} \Arg{A_3} \Arg{A_4} +% \Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} |;| \meta{sign} % \end{quote} -% Compute $Q_{1}$ by evaluating $\meta{A_1}\meta{A_2}0/y - 1$. -% The result will be output to the left, in an \cs{__int_eval:w} -% which we start now. +% Compute $10^{6} + Q_{A}$ (a $7$~digit number thanks to the shift), +% unbrace \meta{A_1} and \meta{A_2}, and prepare the +% \meta{continuation} arguments for $4$ consecutive calls to +% \cs{@@_div_mantissa_calc:wwnnnnnnn}. Each of these calls will need +% \meta{y} (|#1|), and it turns out that we need post-expansion there, +% hence the \cs{__int_value:w}. Here, |#4| is six brace groups, which +% give the six first |n|-type arguments of the \texttt{calc} function. % \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_ii:ww #1; #2; +\cs_new:Npn \@@_div_mantissa_i_o:wnnw #1 ; #2#3 #4 ; { - \exp_after:wN \@@_div_mantissa_iii:www - \__int_value:w #1 \exp_after:wN ; - \__int_value:w - \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn - \int_use:N \__int_eval:w #20/#1 + 999999 ; #2 ; + \exp_after:wN \@@_div_mantissa_test_o:w + \int_use:N \__int_eval:w + \exp_after:wN \@@_div_mantissa_calc:wwnnnnnnn + \int_use:N \__int_eval:w 999999 + #2 #3 0 / #1 ; + #2 #3 ; + #4 + { \exp_after:wN \@@_div_mantissa_ii:wwn \__int_value:w #1 } + { \exp_after:wN \@@_div_mantissa_ii:wwn \__int_value:w #1 } + { \exp_after:wN \@@_div_mantissa_ii:wwn \__int_value:w #1 } + { \exp_after:wN \@@_div_mantissa_iii:wwnnnnn \__int_value:w #1 } } % \end{macrocode} +% \end{macro} +% +% \begin{macro}[int, rEXP]{\@@_div_mantissa_calc:wwnnnnnnn} +% \begin{macro}[aux, rEXP] +% { +% \@@_div_mantissa_calc_i:wwnnnnnnn, +% \@@_div_mantissa_calc_ii:wwnnnnnnn, +% } % \begin{quote} -% \cs{@@_div_mantissa_calc:Nwwnnnnnn} \meta{$10^6+{}$Q_1} |;| -% ~~\meta{A_1} \meta{A_2} |;| \Arg{A_3} \Arg{A_4} -% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign} +% \cs{@@_div_mantissa_calc:wwnnnnnnn} \meta{$10^{6}+{}$Q_{A}} |;| +% \meta{A_1} \meta{A_2} |;| \Arg{A_3} \Arg{A_4} +% \Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} +% \Arg{continuation} % \end{quote} -% The goal here is to expand to +% expands to % \begin{quote} -% \meta{$10^6+{}$Q_1} |;| \meta{B_1} \meta{B_2} |;| \Arg{B_3} \Arg{B_4} -% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign} +% \meta{$10^{6}+{}$Q_{A}} \meta{continuation} |;| +% \meta{B_1} \meta{B_2} |;| \Arg{B_3} \Arg{B_4} +% \Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} % \end{quote} -% where $B = 10^4 A - Q_{1} \cdot Z$. More generally, this function -% is used with $A\to B$, $B\to C$ and $Q_{1} \to Q_{2}$, etc. -% -% Computing the product $Q_{1} \cdot Z$ is almost simple, since -% $Q_{1}$ is rather small, but not quite: -% the product of $Q_{1}$ with each block of four digits $Z_{i}$ -% is within \TeX{}'s bounds, but we wouldn't be able to use the -% usual trick of adding a large power of $10$ to ensure that the -% number of digits is fixed (see other operations for many examples -% of this). Instead, we split off the digit of $10^5$ in $Q_{1}$ -% (and more generally $Q_{i}$), and do something similar to the -% case of the full multiplication. -% -% We know that $0<Q_{i}<1.8\cdot 10^5$, so $10^6+Q_{i}$ starts -% with the digit $1$, followed by $\#1 = 1$ or $0$, then |#2|, which -% is $5$ more digits. It would be somewhat simpler if we got |#1| -% to be two digits, and |#2| four, but we are constrained by the $9$ -% arguments limit. +% where $B = 10^{4} A - Q_{A} \cdot Z$. This function is also used to +% compute $C$, $D$, $E$ (with the input shifted accordingly), and is +% used in \pkg{l3fp-expo}. +% +% We know that $0<Q_{A}<1.8\cdot 10^{5}$, so the product of $Q_{A}$ +% with each $Z_{i}$ is within \TeX{}'s bounds. However, it is a +% little bit too large for our purposes: we would not be able to use +% the usual trick of adding a large power of $10$ to ensure that the +% number of digits is fixed. +% +% The bound on $Q_{A}$, implies that $10^{6}+Q_{A}$ starts with the +% digit $1$, followed by $0$ or $1$. We test, and call different +% auxiliaries for the two cases. An earlier implementation did the +% tests within the computation, but since we added a +% \meta{continuation}, this is not possible because the macro has $9$ +% parameters. % % The result we want is then (the overall power of $10$ is arbitrary): % \begin{align*} -% &10^{-4} ( \#3 - \#2 \cdot \#6 - 10 \cdot \#1 \cdot \#6\#7 ) -% + 10^{-8} ( \#4 - \#2 \cdot \#7 - 10 \cdot \#1 \cdot \#8 ) \\ -% &+ 10^{-12}( \#5 - \#2 \cdot \#8 - 10 \cdot \#1 \cdot \#9 ) -% + 10^{-16}( - \#2 \cdot \#9 ). +% &10^{-4} ( \#2 - \#1 \cdot \#5 - 10 \cdot \meta{i} \cdot \#5\#6 ) +% + 10^{-8} ( \#3 - \#1 \cdot \#6 - 10 \cdot \meta{i} \cdot \#7 ) \\ +% &+ 10^{-12}( \#4 - \#1 \cdot \#7 - 10 \cdot \meta{i} \cdot \#8 ) +% + 10^{-16}( - \#1 \cdot \#8 ), % \end{align*} -% The factors of $10$ come from the fact that -% $Q_{i} = 10\cdot 10^4 \cdot \#1 + \#2$. As usual, to combine -% all the terms, we need to choose some shifts which must ensure -% that the number of digits of the second, third, and fourth terms -% are each fixed. Here, a good choice is $2\cdot 10^9$. -% We are flirting with \TeX{}'s limits once more. -% -% If $\#1=0$, then each term in parentheses (omitting the first) -% is in the open interval $(-10^9, 10^4)$. Thus, adding -% $2\cdot 10^9$ to it gives a $10$ digits number.\footnote{Bruno: -% check that the carry from below does not screw that up. This -% requires slightly tighter bounds.} -% -% If $\#1=1$, then $\#2 < 7.8 \cdot 10^4$, and each term -% in parentheses (omitting the first) is in the interval -% $(-8\cdot 10^8, 10^4)$, and we are even safer. -% -% We add the terms containing $\#1$ in a slightly tricky way -% for efficiency reasons: if $\#1=0$, no need to do any computation, -% while if $\#1=1$ we want $10$ times some number, simply obtained -% by appending a $0$ digit. +% where \meta{i} stands for the $10^{5}$ digit of $Q_{A}$, which is +% $0$ or~$1$, and $\#1$, $\#2$, \emph{etc.\@} are the parameters of +% either auxiliary. The factors of $10$ come from the fact that +% $Q_{A} = 10\cdot 10^{4} \cdot \meta{i} + \#1$. As usual, to combine +% all the terms, we need to choose some shifts which must ensure that +% the number of digits of the second, third, and fourth terms are each +% fixed. Here, the positive contributions are at most $10^{8}$ and +% the negative contributions can go up to $10^{9}$. Indeed, for the +% auxiliary with $\meta{i}=1$, |#1| is at most $80000$, leading to +% contributions of at worse $-8\cdot 10^{8}4$, while the other +% negative term is very small $<10^{6}$ (except in the first +% expression, where we don't care about the number of digits); for the +% auxiliary with $\meta{i}=0$, |#1| can go up to $99999$, but there is +% no other negative term. Hence, a good choice is $2\cdot 10^{9}$, +% which produces totals in the range $[10^{9}, 2.1\cdot 10^{9}]$. We +% are flirting with \TeX{}'s limits once more. % \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_calc:Nwwnnnnnn 1#1#2; #3;#4#5 #6#7#8#9 +\cs_new:Npn \@@_div_mantissa_calc:wwnnnnnnn 1#1 { - 1 #1 #2 \exp_after:wN ; - \int_use:N \__int_eval:w - - 200000 + #3 - #2 * #6 - \if_meaning:w 1 #1 - - #6#70 - \fi: - + - \exp_after:wN \@@_div_mantissa_calc_last:NNNNNN - \int_use:N \__int_eval:w - 1999800000 + #4 - #2*#7 - \if_meaning:w 1 #1 - - #80 - \fi: - + - \exp_after:wN \@@_div_mantissa_calc_pack:NNNNNNw - \int_use:N \__int_eval:w - 1999800000 + #5 - #2*#8 - \if_meaning:w 1 #1 - - #90 - \fi: - + - \exp_after:wN \@@_div_mantissa_calc_pack:NNNNNNw - \int_use:N \__int_eval:w 2000000000 - #2*#9 ; - {#6}{#7}{#8}{#9} + \if_meaning:w 1 #1 + \exp_after:wN \@@_div_mantissa_calc_i:wwnnnnnnn + \else: + \exp_after:wN \@@_div_mantissa_calc_ii:wwnnnnnnn + \fi: } -\cs_new:Npn \@@_div_mantissa_calc_pack:NNNNNNw #1#2#3#4#5#6 #7; - { #1#2#3#4#5#6 ; {#7} } -\cs_new:Npn \@@_div_mantissa_calc_last:NNNNNN #1#2#3#4#5#6 - { #1#2#3#4#5#6 \__int_eval_end: } -% \end{macrocode} -% \begin{quote} -% \cs{@@_div_mantissa_iii:www} \meta{y} |;| \meta{$10^6+{}$Q_1} |;| -% ~~\meta{B_1} \meta{B_2} |;| \Arg{B_3} \Arg{B_4} -% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign} -% \end{quote} -% \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_iii:www #1; #2; #3; +\cs_new:Npn \@@_div_mantissa_calc_i:wwnnnnnnn #1; #2;#3#4 #5#6#7#8 #9 { - \exp_after:wN \@@_div_mantissa_iii_after:w - \int_use:N \__int_eval:w #2 - \exp_after:wN \@@_div_mantissa_iv:www - \__int_value:w #1 \exp_after:wN ; - \__int_value:w - \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn - \int_use:N \__int_eval:w #30/#1 + 999999 ; - #3 ; + 1 1 #1 + #9 \exp_after:wN ; + \int_use:N \__int_eval:w \c_@@_Bigg_leading_shift_int + + #2 - #1 * #5 - #5#60 + \exp_after:wN \@@_pack_Bigg:NNNNNNw + \int_use:N \__int_eval:w \c_@@_Bigg_middle_shift_int + + #3 - #1 * #6 - #70 + \exp_after:wN \@@_pack_Bigg:NNNNNNw + \int_use:N \__int_eval:w \c_@@_Bigg_middle_shift_int + + #4 - #1 * #7 - #80 + \exp_after:wN \@@_pack_Bigg:NNNNNNw + \int_use:N \__int_eval:w \c_@@_Bigg_trailing_shift_int + - #1 * #8 ; + {#5}{#6}{#7}{#8} } -% \end{macrocode} -% \begin{quote} -% \cs{@@_div_mantissa_iv:www} \meta{y} |;| \meta{$10^6+{}$Q_2} |;| -% ~~\meta{C_1} \meta{C_2} |;| \Arg{C_3} \Arg{C_4} -% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign} -% \end{quote} -% \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_iv:www #1; #2; #3; +\cs_new:Npn \@@_div_mantissa_calc_ii:wwnnnnnnn #1; #2;#3#4 #5#6#7#8 #9 { - \exp_after:wN \@@_div_mantissa_pack:NNN - \int_use:N \__int_eval:w #2 - \exp_after:wN \@@_div_mantissa_v:www - \__int_value:w #1 \exp_after:wN ; - \__int_value:w - \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn - \int_use:N \__int_eval:w #30/#1 + 999999 ; - #3 ; + 1 0 #1 + #9 \exp_after:wN ; + \int_use:N \__int_eval:w \c_@@_Bigg_leading_shift_int + + #2 - #1 * #5 + \exp_after:wN \@@_pack_Bigg:NNNNNNw + \int_use:N \__int_eval:w \c_@@_Bigg_middle_shift_int + + #3 - #1 * #6 + \exp_after:wN \@@_pack_Bigg:NNNNNNw + \int_use:N \__int_eval:w \c_@@_Bigg_middle_shift_int + + #4 - #1 * #7 + \exp_after:wN \@@_pack_Bigg:NNNNNNw + \int_use:N \__int_eval:w \c_@@_Bigg_trailing_shift_int + - #1 * #8 ; + {#5}{#6}{#7}{#8} } % \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[aux, EXP]{\@@_div_mantissa_ii:wwn} % \begin{quote} -% \cs{@@_div_mantissa_v:www} \meta{y} |;| \meta{$10^6+{}$Q_3} |;| -% ~~\meta{D_1} \meta{D_2} |;| \Arg{D_3} \Arg{D_4} -% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign} +% \cs{@@_div_mantissa_ii:wwn} \meta{y} |;| +% \meta{B_1} |;| \Arg{B_2} \Arg{B_3} \Arg{B_4} +% \Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} +% \meta{continuations} \meta{sign} % \end{quote} +% Compute $Q_{B}$ by evaluating $\meta{B_1}\meta{B_2}0 / y - 1$. The +% result will be output to the left, in an \cs{__int_eval:w} which we +% start now. Once that is evaluated (and the other $Q_{i}$ also, +% since later expansions are triggered by this one), a packing +% auxiliary takes care of placing the digits of $Q_{B}$ in an +% appropriate way for the final addition to obtain $Q$. This +% auxiliary is also used to compute $Q_{C}$ and $Q_{D}$ with the +% inputs $C$ and $D$ instead of $B$. % \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_v:www #1; #2; #3; +\cs_new:Npn \@@_div_mantissa_ii:wwn #1; #2;#3 { \exp_after:wN \@@_div_mantissa_pack:NNN - \int_use:N \__int_eval:w #2 - \exp_after:wN \@@_div_mantissa_vi:wwnnnn - \__int_value:w - \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn - \int_use:N \__int_eval:w #30/#1 + 999999 ; - #3 ; + \int_use:N \__int_eval:w + \exp_after:wN \@@_div_mantissa_calc:wwnnnnnnn + \int_use:N \__int_eval:w 999999 + #2 #3 0 / #1 ; #2 #3 ; } % \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux, rEXP]{\@@_div_mantissa_iii:wwnnnnn} % \begin{quote} -% \cs{@@_div_mantissa_vi:wwnnnn} \meta{$10^6+{}$Q_4} |;| -% ~~\meta{E_1} \meta{E_2} |;| \Arg{E_3} \Arg{E_4} -% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign} +% \cs{@@_div_mantissa_iii:wwnnnnn} \meta{y} |;| +% \meta{E_1} |;| \Arg{E_2} \Arg{E_3} \Arg{E_4} +% \Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign} % \end{quote} -% We compute $P$ by rounding $2 E_{1} E_{2}/Z_{1}Z_{2}$. +% We compute $P \simeq 2E/Z$ by rounding $2 E_{1} E_{2}/Z_{1}Z_{2}$. +% Note the first $0$, which multiplies $Q_{D}$ by $10$: we will later +% add (roughly) $5\cdot P$, which amounts to adding $P/2 \simeq E/Z$ +% to $Q_{D}$, the appropriate correction from a hypothetical $Q_{E}$. % \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_vi:wwnnnn #1; #2;#3#4 #5#6 +\cs_new:Npn \@@_div_mantissa_iii:wwnnnnn #1; #2;#3#4#5 #6#7 { - \exp_after:wN \@@_div_mantissa_pack:NNN - \int_use:N \__int_eval:w #10 - \exp_after:wN \@@_div_mantissa_vii:wwnnnnnn - \int_use:N \__int_eval:w (\c_two*#2)/#5#6 ; % <- P - #2;{#3}{#4} - {#5}{#6} + 0 + \exp_after:wN \@@_div_mantissa_iv:wwnnnnnnn + \int_use:N \__int_eval:w (\c_two * #2 #3) / #6 #7 ; % <- P + #2 ; {#3} {#4} {#5} + {#6} {#7} } % \end{macrocode} -% Note that we used |#10| instead of |#2| which we had previously. -% Two reasons: firstly, since we dropped $y$, the argument which -% holds $Q_{i}$ has changed, and secondly, we will want the -% fourth piece of the result to have $5$ digits, including the -% \meta{rounding} digit, which we shall compute now from $P$. +% \end{macro} +% +% \begin{macro}[aux, rEXP] +% { +% \@@_div_mantissa_iv:wwnnnnnnn, +% \@@_div_mantissa_v:NNw, +% \@@_div_mantissa_vi:Nw +% } % \begin{quote} -% \cs{@@_div_mantissa_vii:wwnnnnnn} \meta{P} |;| -% ~~\meta{E_1} \meta{E_2} |;| \Arg{E_3} \Arg{E_4} -% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign} +% \cs{@@_div_mantissa_iv:wwnnnnnnn} \meta{P} |;| +% \meta{E_1} |;| \Arg{E_2} \Arg{E_3} \Arg{E_4} +% \Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign} % \end{quote} -% Then compute $2E-PZ$. Once more, we need to be careful and show -% that the calculation $\#1\cdot\#5\#6$ below does not cause an -% overflow: naively, $P$ can be up to $35$, and $\#5\#6$ up to -% $10^8$, but both cannot happen simultaneously. To show that things -% are fine, we split in two (non-disjoint) cases. +% This adds to the current expression ($10^{7} + 10\cdot Q_{D}$) a +% contribution of $5 \cdot P + \operatorname{sign}(T)$ with $T = 2 E - +% P Z$. This amounts to adding $P / 2$ to $Q_{D}$, with an extra +% \meta{rounding} digit. This \meta{rounding} digit is $0$ or $5$ if +% $T$ does not contribute, \emph{i.e.,} if $0 = T = 2 E - P Z$, in +% other words if $10^{16} A / Z$ is an integer or half-integer. +% Otherwise it is in the appropriate range, $[1,4]$ or $[6,9]$. This +% is precise enough for rounding purposes (in any mode). +% +% It seems an overkill to compute $T$ exactly as I do here, but I see +% no faster way right now. +% +% Once more, we need to be careful and show that the calculation +% $\#1\cdot\#6\#7$ below does not cause an overflow: naively, $P$ can +% be up to $35$, and $\#6\#7$ up to $10^{8}$, but both cannot happen +% simultaneously. To show that things are fine, we split in two +% (non-disjoint) cases. % \begin{itemize} -% \item For small $P$, say, $P< 10$, the product obeys -% $P\cdot\#5\#6 < 10^8 \cdot P < 10^9 $. -% \item For large $P$, say, $P\geq 3$, the rounding error on $P$, -% which is at most $1$, is less than a factor of $2$, hence -% $P\leq 4E/Z$, and $P\cdot \#5\#6 \leq 4E\cdot 10^8 < 10^9$. +% \item For $P < 10$, the product obeys $P\cdot\#6\#7 < 10^{8} \cdot P +% < 10^{9} $. +% \item For large $P\geq 3$, the rounding error on $P$, which is at +% most $1$, is less than a factor of $2$, hence $P\leq 4E/Z$. Also, +% $\#6\#7 \leq 10^{8} \cdot Z$, hence $P\cdot \#6\#7 \leq 4E\cdot +% 10^{8} < 10^{9}$. % \end{itemize} % Both inequalities could be made tighter if needed. % -% Note however that $P\cdot \#7\#8$ may overflow, -% since the two factors are now independent, and the result may reach -% $3.5\cdot 10^9$. -% -% Also, we add $10\cdot P/2$ to the \enquote{fourth piece} of the result -% as a first estimate of $10$ times $E/Z$. The goal is that the last digit -% (for now $0$ or $5$) should be the \meta{rounding} digit. More precisely, -% it will be corrected later by adding or subtracting $1$ depending on -% whether $F$ was the correct integer part, or an overestimate (and nothing -% is added when the quotient was exact). This does not give the -% \enquote{correct} \meta{rounding} digit, but it always gives a digit -% in the right \enquote{class} ($0$, $[1,4]$, $5$, or $[6-9]$), enough -% for rounding purposes. +% Note however that $P\cdot \#8\#9$ may overflow, since the two +% factors are now independent, and the result may reach $3.5\cdot +% 10^{9}$. Thus we compute the two lower levels separately. The rest +% is standard, except that we use |+| as a separator (ending integer +% expressions explicitly). $T$ is negative if the first character is +% |-|, it is positive if the first character is neither |0| nor |-|. +% It is also positive if the first character is |0| and second +% argument of \cs{@@_div_mantissa_vi:Nw}, a sum of several terms, is +% also zero. Otherwise, there was an exact agreement: $T = 0$. % \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_vii:wwnnnnnn #1; #2;#3#4 #5#6#7#8 +\cs_new:Npn \@@_div_mantissa_iv:wwnnnnnnn #1; #2;#3#4#5 #6#7#8#9 { + \c_five * #1 - \exp_after:wN \@@_div_mantissa_ix:Nww - \int_use:N \__int_eval:w -20 + 2*#2 - #1*#5#6 + - \exp_after:wN \@@_div_mantissa_viii:NNw - \int_use:N \__int_eval:w 199980 + 2*#3 - #1*#7 + - \exp_after:wN \@@_div_mantissa_viii:NNw - \int_use:N \__int_eval:w 200000 + 2*#4 - #1*#8 ; ; + \exp_after:wN \@@_div_mantissa_vi:Nw + \int_use:N \__int_eval:w -20 + 2*#2#3 - #1*#6#7 + + \exp_after:wN \@@_div_mantissa_v:NN + \int_use:N \__int_eval:w 199980 + 2*#4 - #1*#8 + + \exp_after:wN \@@_div_mantissa_v:NN + \int_use:N \__int_eval:w 200000 + 2*#5 - #1*#9 ; } -\cs_new:Npn \@@_div_mantissa_viii:NNw #1#2#3; { #1#2 ; + #3 } -% \end{macrocode} -% \begin{quote} -% \cs{@@_div_mantissa_ix:Nww} -% ~~\meta{F_1} \meta{F_2} |;| |+| \meta{F_3} |+| \meta{F_4} |;| \meta{sign} -% \end{quote} -% where $F=2E-PZ$. We only need to know whether it is positive, -% negative, or exactly zero. -% \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_ix:Nww #1#2;#3; +\cs_new:Npn \@@_div_mantissa_v:NN #1#2 { #1#2 \__int_eval_end: + } +\cs_new:Npn \@@_div_mantissa_vi:Nw #1#2; { \if_meaning:w 0 #1 - \exp_after:wN \@@_div_mantissa_x:w - \int_use:N \__int_eval:w #3 + \if_int_compare:w \__int_eval:w #2 > \c_zero + \c_one \fi: \else: - \if_meaning:w - #1 - - - \else: - + - \fi: - \c_one - \fi: - ; - } -\cs_new:Npn \@@_div_mantissa_x:w #1; - { - \if_int_compare:w #1 > \c_zero - + \c_one + \if_meaning:w - #1 - \else: + \fi: \c_one \fi: ; } % \end{macrocode} -% We now obtain the following code, where \TeX{} is in the process -% of expanding each of the integer expressions, and thus expands -% the function at the bottom before the ones above it. +% \end{macro} +% +% \begin{macro}[aux, EXP]{\@@_div_mantissa_pack:NNN} +% At this stage, we are in the following situation: \TeX{} is in the +% process of expanding several integer expressions, thus functions at +% the bottom expand before those above. % \begin{quote} -% \cs{@@_div_mantissa_iii_after:w} $10^6 + Q_{1}$ -% \cs{@@_div_mantissa_pack:NNN} $10^6 + Q_{2}$ -% \cs{@@_div_mantissa_pack:NNN} $10^6 + Q_{3}$ +% \cs{@@_div_mantissa_test_o:w} $10^{6} + Q_{A}$ +% \cs{@@_div_mantissa_pack:NNN} $10^{6} + Q_{B}$ +% \cs{@@_div_mantissa_pack:NNN} $10^{6} + Q_{C}$ % \cs{@@_div_mantissa_pack:NNN} -% $10^7 + 10\cdot Q_{4} + 5 \cdot P + \varepsilon$ |;| \meta{sign} +% $10^{7} + 10\cdot Q_{D} + 5 \cdot P + \varepsilon$ |;| \meta{sign} % \end{quote} -% Here, $\varepsilon$ is $0$ in case $2E=PZ$ (\emph{i.e.}, $F=0$), -% $1$ in case $2E>PZ$, which means that $P$ was the correct value, -% but not with an exact quotient, and $-1$ if $2E<PZ$, \emph{i.e.}, -% $P$ was an overestimate. +% Here, $\varepsilon = \operatorname{sign}(T)$ is $0$ in case $2E=PZ$, +% $1$ in case $2E>PZ$, which means that $P$ was the correct value, but +% not with an exact quotient, and $-1$ if $2E<PZ$, \emph{i.e.}, $P$ +% was an overestimate. The packing function we define now does +% nothing special: it removes the $10^{6}$ and carries two digits (for +% the $10^{5}$'s and the $10^{4}$'s). % \begin{macrocode} \cs_new:Npn \@@_div_mantissa_pack:NNN 1 #1 #2 { + #1 #2 ; } % \end{macrocode} -% Once those have been expanded, we get +% \end{macro} +% +% \begin{macro}[aux, rEXP]{\@@_div_mantissa_test_o:w} % \begin{quote} -% \cs{@@_div_mantissa_iii_after:w} |1| |0| \meta{5d} |;| +% \cs{@@_div_mantissa_test_o:w} |1| |0| \meta{5d} |;| % ~~\meta{4d} |;| \meta{4d} |;| \meta{5d} |;| \meta{sign} % \end{quote} -% The reason we know that the first two digits are |1| and |0| -% is that the final result is known to be between $0.1$ (inclusive) -% and $10$, hence $\widetilde{Q_{1}}$ (the tilde denoting the -% contribution from the other $Q_{i}$) is at most $99999$, -% and $10^6+\widetilde{Q_{1}} = 10\cdots$. -% -% It is now time to round. This depends on how many digits -% the final result will have. +% The reason we know that the first two digits are |1| and |0| is that +% the final result is known to be between $0.1$ (inclusive) and $10$, +% hence $\widetilde{Q_{A}}$ (the tilde denoting the contribution from +% the other $Q_{i}$) is at most $99999$, and $10^{6}+\widetilde{Q_{A}} +% = 10\cdots$. +% +% It is now time to round. This depends on how many digits the final +% result will have. % \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_iii_after:w 10 #1 +\cs_new:Npn \@@_div_mantissa_test_o:w 10 #1 { \if_meaning:w 0 #1 - \exp_after:wN \@@_div_mantissa_small:wwwNNNNwN + \exp_after:wN \@@_div_mantissa_small_o:wwwNNNNwN \else: - \exp_after:wN \@@_div_mantissa_large:wwwNNNNwN + \exp_after:wN \@@_div_mantissa_large_o:wwwNNNNwN \fi: #1 } % \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux, EXP]{\@@_div_mantissa_small_o:wwwNNNNwN} % \begin{quote} -% \cs{@@_div_mantissa_small:wwwNNNNwN} |0| \meta{4d} |;| -% ~~\meta{4d} |;| \meta{4d} |;| \meta{5d} |;| \meta{sign} +% \cs{@@_div_mantissa_small_o:wwwNNNNwN} |0| \meta{4d} |;| +% ~~\meta{4d} |;| \meta{4d} |;| \meta{5d} |;| \meta{final sign} % \end{quote} +% Standard use of \cs{@@_basics_pack_low:NNNNNw} and +% \cs{@@_basics_pack_high:NNNNNw}. We finally get to use the +% \meta{final sign} which has been sitting there for a while. % \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_small:wwwNNNNwN +\cs_new:Npn \@@_div_mantissa_small_o:wwwNNNNwN 0 #1; #2; #3; #4#5#6#7#8; #9 { \exp_after:wN \@@_basics_pack_high:NNNNNw @@ -1573,36 +1570,42 @@ \exp_after:wN ; } % \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux, rEXP]{\@@_div_mantissa_large_o:wwwNNNNwN} % \begin{quote} -% \cs{@@_div_mantissa_large:wwwNNNNwN} \meta{5d} |;| +% \cs{@@_div_mantissa_large_o:wwwNNNNwN} \meta{5d} |;| % ~~\meta{4d} |;| \meta{4d} |;| \meta{5d} |;| \meta{sign} % \end{quote} -% \footnote{Bruno: rename the \enquote{add mantissa carry pack} function.} +% We know that the final result cannot reach $10$, hence |1#1#2|, +% together with contributions from the level below, cannot reach +% $2\cdot 10^{9}$. For rounding, we build the \meta{rounding digit} +% from the last two of our $18$ digits. % \begin{macrocode} -\cs_new:Npn \@@_div_mantissa_large:wwwNNNNwN +\cs_new:Npn \@@_div_mantissa_large_o:wwwNNNNwN #1; #2; #3; #4#5#6#7#8; #9 { + \c_one - \exp_after:wN \@@_div_mantissa_large_pack:NNNNNNNNw - \int_use:N \__int_eval:w 1 #1 #2 %<- 1+9d - \exp_after:wN \@@_add_mantissa_carry_pack_ii:NNNNw - \int_use:N \__int_eval:w 1 #3 #4 #5 #6 - + \@@_round:NNNN #9 #6 #7 #8 - \exp_after:wN ; + \exp_after:wN \@@_basics_pack_weird_high:NNNNNNNNw + \int_use:N \__int_eval:w 1 #1 #2 + \exp_after:wN \@@_basics_pack_weird_low:NNNNw + \int_use:N \__int_eval:w 1 #3 #4 #5 #6 + + \exp_after:wN \@@_round:NNN + \exp_after:wN #9 + \exp_after:wN #6 + \__int_value:w \@@_round_digit:Nw #7 #8 ; + \exp_after:wN ; } -\cs_new:Npn \@@_div_mantissa_large_pack:NNNNNNNNw - 1 #1#2#3#4 #5#6#7#8 #9; { ; {#1#2#3#4} {#5#6#7#8} {#9} } % \end{macrocode} % \end{macro} % % \subsection{Unary operations} % -% \begin{macro}{\@@_neg:w} -% This function flips the sign of the \meta{floating point} -% and expands after it in the input stream, just like -% \cs{@@_+_o:ww} etc. +% \begin{macro}[int, EXP]{\@@_neg_o:w} +% This function flips the sign of the \meta{floating point} and +% expands after it in the input stream, just like \cs{@@_+_o:ww} etc. % \begin{macrocode} -\cs_new:Npn \@@_neg:w \s_@@ \@@_chk:w #1 #2 +\cs_new:Npn \@@_neg_o:w \s_@@ \@@_chk:w #1 #2 { \exp_after:wN \@@_exp_after_o:w \exp_after:wN \s_@@ @@ -1613,13 +1616,19 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}{\@@_abs:w} +% \begin{macro}[int, EXP]{\@@_abs_o:w} % This function sets the sign of the \meta{floating point} to be % positive, and expands after itself in the input stream, just like -% \cs{@@_neg:w}. +% \cs{@@_neg_o:w}. We must leave the sign of \texttt{nan} invariant. % \begin{macrocode} -\cs_new:Npn \@@_abs:w \s_@@ \@@_chk:w #1 #2 - { \@@_exp_after_o:w \s_@@ \@@_chk:w #1 0 } +\cs_new:Npn \@@_abs_o:w \s_@@ \@@_chk:w #1 #2 + { + \exp_after:wN \@@_exp_after_o:w + \exp_after:wN \s_@@ + \exp_after:wN \@@_chk:w + \exp_after:wN #1 + \__int_value:w \if_meaning:w 1 #2 1 \else: 0 \fi: \exp_stop_f: + } % \end{macrocode} % \end{macro} % @@ -1631,4 +1640,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx index 057cef4b176..8f0c2848ea4 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx @@ -35,8 +35,8 @@ %% % %<*driver> -\RequirePackage{l3names} -\GetIdInfo$Id: l3fp-convert.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3fp-convert.dtx 4090 2012-08-14 07:57:01Z joseph $ {L3 Floating-point conversion} \documentclass[full]{l3doc} \begin{document} @@ -66,9 +66,6 @@ % % \begin{documentation} % -% ^^A todo: tests -% ^^A todo: doc functions -% % \end{documentation} % % \begin{implementation} @@ -92,7 +89,7 @@ % as an end-delimiter for its first argument, and the second argument % is the same \texttt{loop} auxiliary. Once the last trailing zero is % reached, the second argument will be the \texttt{dot} auxiliary, -% which removes a trailing dot if any. We then cleanup with the +% which removes a trailing dot if any. We then clean-up with the % \texttt{end} auxiliary, keeping only the number. % \begin{macrocode} \cs_new:Npn \@@_trim_zeros:w #1 ; @@ -109,28 +106,17 @@ % % \subsection{Scientific notation} % -% \begin{variable}{\c_@@_scientific_inf_tl} -% Result of converting $\infty$ to a scientific representation: after -% triggering an \enquote{invalid operation} exception, -% \cs{fp_to_scientific:n} yields that result, larger than any finite -% floating point number. -% \begin{macrocode} -\tl_const:Nx \c_@@_scientific_inf_tl - { 1e \int_use:N \c_@@_max_exponent_int } -% \end{macrocode} -% \end{variable} -% -% \begin{macro} +% \begin{macro}[EXP] % {\fp_to_scientific:N, \fp_to_scientific:c, \fp_to_scientific:n} % The three public functions evaluate their argument, then pass it to % \cs{@@_to_scientific:w}. % \begin{macrocode} \cs_new:Npn \fp_to_scientific:N #1 { \exp_after:wN \@@_to_scientific:w #1 } \cs_generate_variant:Nn \fp_to_scientific:N { c } -\cs_new:Npn \fp_to_scientific:n #1 +\cs_new_nopar:Npn \fp_to_scientific:n { \exp_after:wN \@@_to_scientific:w - \tex_romannumeral:D -`0 \@@_parse:n {#1} + \tex_romannumeral:D -`0 \@@_parse:n } % \end{macrocode} % \end{macro} @@ -143,43 +129,63 @@ % } % Expressing an internal floating point number in scientific notation % is quite easy: no rounding, and the format is very well defined. -% First cater for the sign: negative numbers (|#2=2|) start with |-|. -% Then filter the special cases: we insert \cs{prg_do_nothing:} -% because \cs{@@_invalid_operation:Nnw} expands after taking one -% floating point argument. In the normal case, decrement the exponent -% and unbrace the $4$ brace groups, then in a second step grab the -% first digit (previously hidden in braces) to order the various parts -% correctly. Finally trim zeros. +% First cater for the sign: negative numbers ($|#2|=2$) start +% with~|-|; we then only need to care about positive numbers and +% \texttt{nan}. Then filter the special cases: $\pm0$~are represented +% as~|0|; infinities are converted to a number slightly larger than +% the largest after an \enquote{invalid_operation} exception; +% \texttt{nan} is represented as~|0| after an +% \enquote{invalid_operation} exception. In the normal case, +% decrement the exponent and unbrace the $4$ brace groups, then in a +% second step grab the first digit (previously hidden in braces) to +% order the various parts correctly. Finally trim zeros. The whole +% construction is within a call to \cs{tl_to_lowercase:n}, responsible +% for creating |e| with category \enquote{other}. % \begin{macrocode} -\cs_new:Npn \@@_to_scientific:w \s_@@ \@@_chk:w #1#2#3 ; +\group_begin: +\char_set_catcode_other:N E +\tl_to_lowercase:n { - \if_meaning:w 2 #2 \exp_after:wN - \tex_romannumeral:D -`0 \fi: - \if_case:w #1 \exp_stop_f: - \@@_case_return:nw { \exp_after:wN 0 } - \or: \exp_after:wN \@@_to_scientific_normal:wnnnnn - \or: - \@@_case_use:nw - { - \@@_invalid_operation:Nnw - \c_@@_scientific_inf_tl { fp_to_scientific } - } - \or: - \@@_case_use:nw - { \@@_invalid_operation:Nnw 0 { fp_to_scientific } } - \fi: - \s_@@ \@@_chk:w #1 #2 #3 ; \prg_do_nothing: - } -\cs_new:Npn \@@_to_scientific_normal:wnnnnn - \s_@@ \@@_chk:w 1 #1 #2 #3#4#5#6 ; \prg_do_nothing: - { - \if_int_compare:w #2 = \c_one - \exp_after:wN \@@_to_scientific_normal:wNw - \else: - \exp_after:wN \@@_to_scientific_normal:wNw - \exp_after:wN e - \int_use:N \__int_eval:w #2 - \c_one - \fi: - ; #3 #4 #5 #6 ; + \group_end: + \cs_new:Npn \@@_to_scientific:w \s_@@ \@@_chk:w #1#2 + { + \if_meaning:w 2 #2 \exp_after:wN - \tex_romannumeral:D -`0 \fi: + \if_case:w #1 \exp_stop_f: + \@@_case_return:nw { 0 } + \or: \exp_after:wN \@@_to_scientific_normal:wnnnnn + \or: + \@@_case_use:nw + { + \@@_invalid_operation:nnw + { + \exp_after:wN 1 + \exp_after:wN E + \int_use:N \c_@@_max_exponent_int + } + { fp_to_scientific } + } + \or: + \@@_case_use:nw + { + \@@_invalid_operation:nnw + { 0 } + { fp_to_scientific } + } + \fi: + \s_@@ \@@_chk:w #1 #2 + } + \cs_new:Npn \@@_to_scientific_normal:wnnnnn + \s_@@ \@@_chk:w 1 #1 #2 #3#4#5#6 ; + { + \if_int_compare:w #2 = \c_one + \exp_after:wN \@@_to_scientific_normal:wNw + \else: + \exp_after:wN \@@_to_scientific_normal:wNw + \exp_after:wN E + \int_use:N \__int_eval:w #2 - \c_one + \fi: + ; #3 #4 #5 #6 ; + } } \cs_new:Npn \@@_to_scientific_normal:wNw #1 ; #2#3; { \@@_trim_zeros:w #2.#3 ; #1 } @@ -188,22 +194,6 @@ % % \subsection{Decimal representation} % -% \begin{variable}{\c_@@_decimal_inf_tl} -% Result of converting $\infty$ to a decimal representation: after -% triggering an \enquote{invalid operation} exception, -% \cs{fp_to_decimal:n} yields a~$1$ followed by $\ExplSyntaxOn -% \int_use:N \c__fp_max_exponent_int$~$0$, larger than any finite -% floating point number. Since the expanded token list is very long, -% we use an \texttt{n}-type assignment. -% \begin{macrocode} -\tl_const:Nn \c_@@_decimal_inf_tl - { - \exp_after:wN \exp_after:wN \exp_after:wN 1 - \prg_replicate:nn \c_@@_max_exponent_int 0 - } -% \end{macrocode} -% \end{variable} -% % \begin{macro}[EXP] % {\fp_to_decimal:N, \fp_to_decimal:c, \fp_to_decimal:n} % All three public variants are based on the same \cs{@@_to_decimal:w} @@ -219,7 +209,7 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP, aux] +% \begin{macro}[aux, EXP] % { % \@@_to_decimal:w, % \@@_to_decimal_normal:wnnnnn, @@ -228,35 +218,45 @@ % } % The structure is similar to \cs{@@_to_scientific:w}. Insert |-| for % negative numbers. Zero gives $0$, $\pm\infty$ and \nan{} yield an -% \enquote{invalid operation} exception. Normal numbers with an -% exponent in the range $[1,15]$ have that number of digits before the -% decimal separator: \enquote{decimate} them, and remove leading zeros -% with \cs{__int_value:w}, then trim trailing zeros and dot. Normal +% \enquote{invalid operation} exception; note that $\pm\infty$ +% produces a very large output, which we don't expand now since it +% most likely won't be needed. Normal numbers with an exponent in the +% range $[1,15]$ have that number of digits before the decimal +% separator: \enquote{decimate} them, and remove leading zeros with +% \cs{__int_value:w}, then trim trailing zeros and dot. Normal % numbers with an exponent $16$ or larger have no decimal separator, % we only need to add trailing zeros. When the exponent is % non-positive, the result should be $0.\meta{zeros}\meta{digits}$, % trimmed. % \begin{macrocode} -\cs_new:Npn \@@_to_decimal:w \s_@@ \@@_chk:w #1#2#3 ; +\cs_new:Npn \@@_to_decimal:w \s_@@ \@@_chk:w #1#2 { \if_meaning:w 2 #2 \exp_after:wN - \tex_romannumeral:D -`0 \fi: \if_case:w #1 \exp_stop_f: - \@@_case_return:nw { \exp_after:wN 0 } + \@@_case_return:nw { 0 } \or: \exp_after:wN \@@_to_decimal_normal:wnnnnn \or: \@@_case_use:nw { - \@@_invalid_operation:Nnw - \c_@@_decimal_inf_tl { fp_to_decimal } + \@@_invalid_operation:nnw + { + \exp_after:wN \exp_after:wN \exp_after:wN 1 + \prg_replicate:nn \c_@@_max_exponent_int 0 + } + { fp_to_decimal } } \or: \@@_case_use:nw - { \@@_invalid_operation:Nnw 0 { fp_to_decimal } } + { + \@@_invalid_operation:nnw + { 0 } + { fp_to_decimal } + } \fi: - \s_@@ \@@_chk:w #1 #2 #3 ; \prg_do_nothing: + \s_@@ \@@_chk:w #1 #2 } \cs_new:Npn \@@_to_decimal_normal:wnnnnn - \s_@@ \@@_chk:w 1 #1 #2 #3#4#5#6 ; \prg_do_nothing: + \s_@@ \@@_chk:w 1 #1 #2 #3#4#5#6 ; { \int_compare:nNnTF {#2} > \c_zero { @@ -309,14 +309,12 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP, aux]{\@@_to_tl:w, \@@_to_tl_normal:nnnnn} +% \begin{macro}[aux, EXP]{\@@_to_tl:w, \@@_to_tl_normal:nnnnn} % A structure similar to \cs{@@_to_scientific:w} and % \cs{@@_to_decimal:w}, but without the \enquote{invalid operation} % exception. First filter special cases. We express normal numbers % in decimal notation if the exponent is in the range $[-2,16]$, and -% otherwise use scientific notation. The weird \cs{prg_do_nothing:} -% is needed because the \texttt{decimal} and \texttt{scientific} -% auxiliaries we use expect it. +% otherwise use scientific notation. % \begin{macrocode} \cs_new:Npn \@@_to_tl:w \s_@@ \@@_chk:w #1#2 { @@ -324,11 +322,11 @@ \if_case:w #1 \exp_stop_f: \@@_case_return:nw { 0 } \or: \exp_after:wN \@@_to_tl_normal:nnnnn - \or: \@@_case_return:nw { inf } - \else: \@@_case_return:nw { nan } + \or: \@@_case_return:nw { \tl_to_str:n {inf} } + \else: \@@_case_return:nw { \tl_to_str:n {nan} } \fi: } -\cs_new:Npn \@@_to_tl_normal:nnnnn #1#2 ; +\cs_new:Npn \@@_to_tl_normal:nnnnn #1 { \if_int_compare:w #1 > \c_sixteen \exp_after:wN \@@_to_scientific_normal:wnnnnn @@ -341,24 +339,29 @@ \exp_after:wN \@@_to_decimal_normal:wnnnnn \fi: \fi: - \s_@@ \@@_chk:w 1 0 {#1} #2 ; \prg_do_nothing: + \s_@@ \@@_chk:w 1 0 {#1} } % \end{macrocode} % \end{macro} % % \subsection{Formatting} % -% ^^A todo +% This is not implemented yet, as it is not yet clear what a correct +% interface would be, for this kind of structured conversion from a +% floating point (or other types of variables) to a string. Ideas +% welcome. % % \subsection{Convert to dimension or integer} % % \begin{macro}[EXP]{\fp_to_dim:N, \fp_to_dim:c, \fp_to_dim:n} % These three public functions rely on \cs{fp_to_decimal:n} -% internally. +% internally. We make sure to produce |pt| with category other. % \begin{macrocode} -\cs_new:Npn \fp_to_dim:N #1 { \fp_to_decimal:N #1 pt } +\cs_new:Npx \fp_to_dim:N #1 + { \exp_not:N \fp_to_decimal:N #1 \tl_to_str:n {pt} } \cs_generate_variant:Nn \fp_to_dim:N { c } -\cs_new:Npn \fp_to_dim:n #1 { \fp_to_decimal:n {#1} pt } +\cs_new:Npx \fp_to_dim:n #1 + { \exp_not:N \fp_to_decimal:n {#1} \tl_to_str:n {pt} } % \end{macrocode} % \end{macro} % @@ -385,7 +388,7 @@ \cs_new:Npn \@@_to_int:w #1; { \exp_after:wN \@@_to_decimal:w \tex_romannumeral:D -`0 - \@@_round:Nwn \@@_round_to_nearest:NNN #1; { 0 } \prg_do_nothing: + \@@_round:Nwn \@@_round_to_nearest:NNN #1; { 0 } } % \end{macrocode} % \end{macro} @@ -400,14 +403,12 @@ % \@@_from_dim_ii:wNNnnnnnn, % \@@_from_dim_iii:wnnnnwN, % } -% The dimension expression (which can in fact be a glue expression) -% is evaluated, converted to a number (\emph{i.e.}, expressed in -% scaled points), then multiplied by $2^{-16} = 0.0000152587890625$ -% to give a value expressed in points. We use the auxiliary function -% \begin{quote} -% \cs{@@_mul_npos:Nnwnw} \meta{sign} \newline -% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;| -% \end{quote} +% The dimension expression (which can in fact be a glue expression) is +% evaluated, converted to a number (\emph{i.e.}, expressed in scaled +% points), then multiplied by $2^{-16} = 0.0000152587890625$ to give a +% value expressed in points. The auxiliary \cs{@@_mul_npos_o:Nww} +% expects the desired \meta{final sign} and two floating point +% operands (of the form \cs{s_@@} \ldots{} |;|) as arguments. % \begin{macrocode} \cs_new:Npn \dim_to_fp:n #1 { @@ -417,8 +418,7 @@ \cs_new:Npn \@@_from_dim_test:N #1 { \if_meaning:w 0 #1 - \exp_after:wN \@@_use_i_until_s:nw - \exp_after:wN \c_zero_fp + \@@_case_return:nw \c_zero_fp \else: \if_meaning:w - #1 \exp_after:wN \@@_from_dim:Nw @@ -440,8 +440,9 @@ { \@@_from_dim_iii:wnnnnwN #1 {#2#300} {0000} ; } \cs_new:Npn \@@_from_dim_iii:wnnnnwN #1; #2#3#4#5#6; #7 { - \@@_mul_npos:Nnwnw #7 {#5} #1 ; - {-4} {1525} {8789} {0625} {0000} ; + \@@_mul_npos_o:Nww #7 + \s_@@ \@@_chk:w 1 #7 {#5} #1 ; + \s_@@ \@@_chk:w 1 0 {-4} {1525} {8789} {0625} {0000} ; } % \end{macrocode} % \end{macro} @@ -459,9 +460,12 @@ % \end{macro} % % \begin{macro}[EXP]{\fp_abs:n} -% Trivial but useful. +% Trivial but useful. See the implementation of \cs{fp_add:Nn} for an +% explanation of why to use \cs{@@_parse:n}, namely, for better error +% reporting. % \begin{macrocode} -\cs_new:Npn \fp_abs:n #1 { \fp_to_decimal:n { abs ( #1 ) } } +\cs_new:Npn \fp_abs:n #1 + { \fp_to_decimal:n { abs \@@_parse:n {#1} } } % \end{macrocode} % \end{macro} % @@ -473,4 +477,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx index edf9ac2ad35..fee1b90ed58 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx @@ -35,8 +35,8 @@ %% % %<*driver> -\RequirePackage{l3names} -\GetIdInfo$Id: l3fp-expo.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3fp-expo.dtx 4089 2012-08-14 04:52:20Z bruno $ {L3 Floating-point exponential-related functions} \documentclass[full]{l3doc} \begin{document} @@ -77,21 +77,46 @@ %<@@=fp> % \end{macrocode} % -% \subsection{General comments} +% \subsection{Logarithm} +% +% \subsubsection{Work plan} +% +% As for many other functions, we filter out special cases in +% \cs{@@_ln_o:w}. Then \cs{@@_ln_npos_o:w} receives a positive normal +% number, which we write in the form $a\cdot 10^{b}$ with $a\in[0.1,1)$. % -%^^A todo: redoc -% The algorithm for computing the logarithm of the significand could be -% made to use a $5$ terms Taylor series instead of $10$ terms by taking -% $c = 2000/(\lfloor 200x\rfloor +1) \in [10,95]$ instead of $c\in -% [1,10]$. Also, it would then be possible to simplify the computation -% of $t$, using methods similar to \cs{@@_fixed_div_to_float:ww}. -% However, we would then have to hard-code the logarithms of $44$ small -% integers instead of $9$. +% \emph{The rest of this section is actually not in sync with the code. +% Or is the code not in sync with the section?} +% +% We are given a positive normal number, of the form $a\cdot 10^{b}$ +% with $a\in[0.1,1)$. To compute its logarithm, we find a small integer +% $5\leq c < 50$ such that $0.91 \leq a c / 5 < 1.1$, and use the +% relation +% \begin{equation*} +% \ln (a \cdot 10^b) = b \cdot \ln (10) - \ln (c/5) + \ln (ac/5). +% \end{equation*} +% The logarithms $\ln(10)$ and $\ln(c/5)$ are looked up in a table. The +% last term is computed using the following Talor series of $\ln$ near +% $1$: +% \begin{equation*} +% \ln\left(\frac{ac}{5}\right) +% = \ln\left(\frac{1+t}{1-t}\right) +% = 2t\left(1 + t^2 \left(\frac{1}{3} + t^2 \left(\frac{1}{5} +% + t^2 \left(\frac{1}{7} + t^2 \left( \frac{1}{9} + \cdots +% \right)\right)\right)\right)\right) +% \end{equation*} +% where $t=1-10/(ac+5)$. We can now see one reason for the choice of +% $ac\sim 5$: then $ac+5=10(1-\epsilon)$ with $-0.05<\epsilon\leq +% 0.045$, hence +% \begin{equation*} +% t = \frac{\epsilon}{1-\epsilon} +% = \epsilon (1+\epsilon)(1+\epsilon^2)(1+\epsilon^4)\ldots, +% \end{equation*} +% is not too difficult to compute. % -% \subsection{Some constants} +% \subsubsection{Some constants} % -% ^^A todo: very odd: can I delete ln_ten? -% \begin{variable} +% \begin{variable}[aux] % { % \c_@@_ln_i_fixed_tl , % \c_@@_ln_ii_fixed_tl , @@ -102,89 +127,57 @@ % \c_@@_ln_viii_fixed_tl , % \c_@@_ln_ix_fixed_tl , % \c_@@_ln_x_fixed_tl, -% \c_@@_ln_ten_fixed_tl, % } -% A few values of the logarithm which are needed in the -% implementation. It turns out that we don't need the value of -% $\log(5)$. +% A few values of the logarithm as extended fixed point numbers. +% Those are needed in the implementation. It turns out that we don't +% need the value of $\ln(5)$. % \begin{macrocode} \tl_const:Nn \c_@@_ln_i_fixed_tl { {0000}{0000}{0000}{0000}{0000}{0000} } \tl_const:Nn \c_@@_ln_ii_fixed_tl { {6931}{4718}{0559}{9453}{0941}{7232} } \tl_const:Nn \c_@@_ln_iii_fixed_tl {{10986}{1228}{8668}{1096}{9139}{5245} } \tl_const:Nn \c_@@_ln_iv_fixed_tl {{13862}{9436}{1119}{8906}{1883}{4464} } - % \tl_const:Nn \c_@@_ln_v_fixed_tl {{16094}{3791}{2434}{1003}{7460}{0759} } \tl_const:Nn \c_@@_ln_vi_fixed_tl {{17917}{5946}{9228}{0550}{0081}{2477} } \tl_const:Nn \c_@@_ln_vii_fixed_tl {{19459}{1014}{9055}{3133}{0510}{5353} } \tl_const:Nn \c_@@_ln_viii_fixed_tl{{20794}{4154}{1679}{8359}{2825}{1696} } \tl_const:Nn \c_@@_ln_ix_fixed_tl {{21972}{2457}{7336}{2193}{8279}{0490} } \tl_const:Nn \c_@@_ln_x_fixed_tl {{23025}{8509}{2994}{0456}{8401}{7991} } - %\tl_const:Nn \c_@@_ln_ten_fixed_tl {{23025}{8509}{2994}{0456}{8401}{7991} } % \end{macrocode} % \end{variable} % -% \subsection{Logarithm} -% % \subsubsection{Sign, exponent, and special numbers} % -% \begin{macro}[EXP]{\@@_ln:w} -% The logarithm of $\pm 0$ is $-\infty$, raising a division by zero -% exception. The logarithm of negative numbers (including $-\infty$, -% but not $-0$) raises the \enquote{invalid} exception. The logarithm -% of $+\infty$ or a \texttt{nan} is itself. Positive normal numbers -% call \cs{@@_ln_npos:w}. +% \begin{macro}[EXP, int]{\@@_ln_o:w} +% The logarithm of negative numbers (including $-\infty$ and $-0$) +% raises the \enquote{invalid} exception. The logarithm of $+0$ is +% $-\infty$, raising a division by zero exception. The logarithm of +% $+\infty$ or a \texttt{nan} is itself. Positive normal numbers call +% \cs{@@_ln_npos_o:w}. % \begin{macrocode} -\cs_new:Npn \@@_ln:w \s_@@ \@@_chk:w #1 #2 +\cs_new:Npn \@@_ln_o:w \s_@@ \@@_chk:w #1 #2 { - \if_meaning:w 0 #1 - \@@_case_use:nw - { \@@_division_by_zero:Nnw \c_minus_inf_fp { ln } } - \fi: \if_meaning:w 2 #2 - \@@_case_use:nw - { \@@_invalid_operation:Nnw \c_nan_fp { ln } } + \@@_case_use:nw { \@@_invalid_operation_o:nw { ln } } \fi: - \if_meaning:w 1 #1 \else: + \if_case:w #1 \exp_stop_f: + \@@_case_use:nw + { \@@_division_by_zero_o:Nnw \c_minus_inf_fp { ln } } + \or: + \else: \@@_case_return_same_o:w \fi: - \@@_ln_npos:w \s_@@ \@@_chk:w #1#2 + \@@_ln_npos_o:w \s_@@ \@@_chk:w #1#2 } % \end{macrocode} % \end{macro} % % \subsubsection{Absolute ln} % -% We are given a positive normal number, of the form $a\cdot 10^{b}$ -% with $a\in[0.1,1)$. To compute its logarithm, we find a small integer -% $5\leq c < 50$ such that $0.91 \leq a c / 5 < 1.1$, and use the -% relation -% \[ -% \ln (a \cdot 10^b) = b \cdot \ln (10) - \ln (c/5) + \ln (ac/5). -% \] -% The logarithms $\ln(10)$ and $\ln(c/5)$ are looked up in a table. The -% last term is computed using the following Talor series of $\ln$ near -% $1$: -% \[ -% \ln\left(\frac{ac}{5}\right) -% = \ln\left(\frac{1+t}{1-t}\right) -% = 2t\left(1 + t^2 \left(\frac{1}{3} + t^2 \left(\frac{1}{5} -% + t^2 \left(\frac{1}{7} + t^2 \left( \frac{1}{9} + \cdots -% \right)\right)\right)\right)\right) -% \] -% where $t=1-10/(ac+5)$. We can now see one reason for the choice of -% $ac\sim 5$: then $ac+5=10(1-\epsilon)$ with $-0.05<\epsilon\leq -% 0.045$, hence -% \[ -% t = \frac{\epsilon}{1-\epsilon} -% = \epsilon (1+\epsilon)(1+\epsilon^2)(1+\epsilon^4)\ldots, -% \] -% is not too difficult to compute. -% -% \begin{macro}{\@@_ln_npos:w} +% \begin{macro}[aux, EXP]{\@@_ln_npos_o:w} % We catch the case of a significand very close to $0.1$ or to $1$. % In all other cases, the final result is at least $10^{-4}$, and % then an error of $0.5\cdot 10^{-20}$ is acceptable. % \begin{macrocode} -\cs_new:Npn \@@_ln_npos:w \s_@@ \@@_chk:w 10#1#2#3; +\cs_new:Npn \@@_ln_npos_o:w \s_@@ \@@_chk:w 10#1#2#3; { %^^A todo: ln(1) should be "exact zero", not "underflow" \exp_after:wN \@@_sanitize:Nw \__int_value:w % for the overall sign @@ -201,15 +194,17 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[int, EXP]{\@@_ln_significand:NNNNnnnN} -% \begin{syntax} -% \cs{@@_ln_significand:NNNNnnnN} \meta{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \meta{continuation} -% \end{syntax} +% \begin{macro}[aux, EXP]{\@@_ln_significand:NNNNnnnN} +% \begin{quote} +% \cs{@@_ln_significand:NNNNnnnN} \meta{X_1} \Arg{X_2} \Arg{X_3} +% \Arg{X_4} \meta{continuation} +% \end{quote} % This function expands to % \begin{quote} -% \meta{continuation} \Arg{Y_1} \Arg{Y_2} \Arg{Y_3} \Arg{Y_4} \Arg{Y_5} \Arg{Y_6} |;| +% \meta{continuation} \Arg{Y_1} \Arg{Y_2} \Arg{Y_3} \Arg{Y_4} +% \Arg{Y_5} \Arg{Y_6} |;| % \end{quote} -% where $Y = - \log X$. +% where $Y = - \ln(X)$ as an extended fixed point. % \begin{macrocode} \cs_new:Npn \@@_ln_significand:NNNNnnnN #1#2#3#4 { @@ -232,6 +227,9 @@ ; { #1 #2 #3 #4 } } % \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux, EXP]{\@@_ln_x_ii:wnnnn} % We have thus found $c$. It is chosen such that $0.7\leq ac < 1.4$ % in all cases. Compute $ 1 + x = 1 + ac \in [1.7,2.4)$. % \begin{macrocode} @@ -240,8 +238,8 @@ \exp_after:wN \@@_ln_div_after:Nw \cs:w c_@@_ln_ \tex_romannumeral:D #1 _fixed_tl \exp_after:wN \cs_end: \__int_value:w - \exp_after:wN \@@_ln_x_iv:nnnnnnnn - \tex_romannumeral:D -`0 + \exp_after:wN \@@_ln_x_iv:wnnnnnnnn + \int_use:N \__int_eval:w \exp_after:wN \@@_ln_x_iii_var:NNNNNw \int_use:N \__int_eval:w 9999 9999 + #1*#2#3 + \exp_after:wN \@@_ln_x_iii:NNNNNw @@ -249,7 +247,11 @@ {20000} {0000} {0000} {0000} } %^^A todo: reoptimize (a generalization attempt failed). \cs_new:Npn \@@_ln_x_iii:NNNNNw #1 #2#3#4#5 #6; { #1; {#2#3#4#5} {#6} } -\cs_new:Npn \@@_ln_x_iii_var:NNNNNw #1 #2#3#4#5 #6; { {#1#2#3#4#5} {#6} } +\cs_new:Npn \@@_ln_x_iii_var:NNNNNw #1 #2#3#4#5 #6; + { + #1#2#3#4#5 + \c_one ; + {#1#2#3#4#5} {#6} + } % \end{macrocode} % The Taylor series will be expressed in terms of % $t = (x-1)/(x+1) = 1 - 2/(x+1)$. We now compute the @@ -315,50 +317,41 @@ % a faithful rounding).\footnote{Bruno: to be completed.} % % \begin{quote} -% \cs{@@_ln_x_iv:NNNNNwnn} +% \cs{@@_ln_x_iv:wnnnnnnnn} % \meta{1 or 2} \meta{8d} |;| \Arg{4d} \Arg{4d} \meta{fixed-tl} % \end{quote} % The number is $x$. Compute $y$ by adding 1 to the five first digits. % \begin{macrocode} -\cs_new:Npn \@@_ln_x_iv:nnnnnnnn #1#2#3#4 #5#6#7#8 +\cs_new:Npn \@@_ln_x_iv:wnnnnnnnn #1; #2#3#4#5 #6#7#8#9 { - \exp_after:wN \@@_ln_div_i:w - \int_use:N \__int_eval:w #1 + \c_one ; - #5 #6 ; {#7} {#8} - {#1} {#2} {#3} {#4} + \exp_after:wN \@@_div_mantissa_pack:NNN + \int_use:N \__int_eval:w + \@@_ln_div_i:w #1 ; + #6 #7 ; {#8} {#9} + {#2} {#3} {#4} {#5} + { \exp_after:wN \@@_ln_div_ii:wwn \__int_value:w #1 } + { \exp_after:wN \@@_ln_div_ii:wwn \__int_value:w #1 } + { \exp_after:wN \@@_ln_div_ii:wwn \__int_value:w #1 } + { \exp_after:wN \@@_ln_div_ii:wwn \__int_value:w #1 } + { \exp_after:wN \@@_ln_div_vi:wwn \__int_value:w #1 } } \cs_new:Npn \@@_ln_div_i:w #1; { - \exp_after:wN \@@_ln_div_ii:www - \__int_value:w #1 \exp_after:wN ; - \__int_value:w - \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn - \int_use:N \__int_eval:w 999999 + 2 0000 0000 / #1 ; % Q1 + \exp_after:wN \@@_div_mantissa_calc:wwnnnnnnn + \int_use:N \__int_eval:w 999999 + 2 0000 0000 / #1 ; % Q1 } -\cs_set_protected:Npn \@@_tmp:w #1#2 +\cs_new:Npn \@@_ln_div_ii:wwn #1; #2;#3 % y; B1;B2 <- for k=1 { - \cs_new:Npn #1 ##1; ##2; ##3; % y; Q1; B1B2; <- for k=1 - { - \exp_after:wN \@@_div_mantissa_pack:NNN - \int_use:N \__int_eval:w ##2 - \exp_after:wN #2 - \__int_value:w ##1 \exp_after:wN ; - \__int_value:w - \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn - \int_use:N \__int_eval:w 999999 + ##3 / ##1 ; % Q2 - ##3 ; - } + \exp_after:wN \@@_div_mantissa_pack:NNN + \int_use:N \__int_eval:w + \exp_after:wN \@@_div_mantissa_calc:wwnnnnnnn + \int_use:N \__int_eval:w 999999 + #2 #3 / #1 ; % Q2 + #2 #3 ; } -\@@_tmp:w \@@_ln_div_ii:www \@@_ln_div_iii:www -\@@_tmp:w \@@_ln_div_iii:www \@@_ln_div_iv:www -\@@_tmp:w \@@_ln_div_iv:www \@@_ln_div_v:www -\@@_tmp:w \@@_ln_div_v:www \@@_ln_div_vi:www -\cs_new:Npn \@@_ln_div_vi:www #1; #2; #3;#4#5 #6#7#8#9 %y;Q5;F1F2;F3F4x1x2x3x4 +\cs_new:Npn \@@_ln_div_vi:wwn #1; #2;#3#4#5 #6#7#8#9 %y;F1;F2F3F4x1x2x3x4 { \exp_after:wN \@@_div_mantissa_pack:NNN - \int_use:N \__int_eval:w #2 - \exp_after:wN \@@_div_mantissa_pack:NNN - \int_use:N \__int_eval:w 1000000 + #3 / #1 ; % Q6 + \int_use:N \__int_eval:w 1000000 + #2 #3 / #1 ; % Q6 } % \end{macrocode} % We now have essentially\footnote{Bruno: add a mention that @@ -521,14 +514,14 @@ % \Arg{r_1} \Arg{r_2} \Arg{r_3} \Arg{r_4} \Arg{r_5} \Arg{r_6} |;| % \meta{fixed tl} \meta{exponent} |;| \meta{continuation} % \end{quote} -% We are now reduced to finding $\ln c$ and $\meta{exponent}\ln 10$ +% We are now reduced to finding $\ln(c)$ and $\meta{exponent}\ln(10)$ % in a table, and adding it to the mixture. The first step is to -% get $\ln c - \ln x = - \ln a$, then we get $|b|\ln 10$ and add +% get $\ln(c) - \ln(x) = - \ln(a)$, then we get $|b|\ln(10)$ and add % or subtract. % -% For now, $\ln x$ is given as $\cdot 10^0$. Unless both the exponent +% For now, $\ln(x)$ is given as $\cdot 10^0$. Unless both the exponent % is $1$ and $c=1$, we shift to working in units of $\cdot 10^4$, -% since the final result will be at least $\ln 10/7 \simeq +% since the final result will be at least $\ln(10/7) \simeq % 0.35$.\footnote{Bruno: that was wrong at some point, I must check.} % \begin{macrocode} \cs_new:Npn \@@_ln_c:NwNw #1 #2; #3 @@ -550,9 +543,9 @@ % \Arg{s_1} \Arg{s_2} \Arg{s_3} \Arg{s_4} \Arg{s_5} \Arg{s_6} |;| % \Arg{exponent} % \end{quote} -% Compute \meta{exponent} times $\ln 10$. Apart from the cases where +% Compute \meta{exponent} times $\ln(10)$. Apart from the cases where % \meta{exponent} is $0$ or $1$, the result will necessarily be at -% least $\ln 10 \simeq 2.3$ in magnitude. We can thus drop the least +% least $\ln(10) \simeq 2.3$ in magnitude. We can thus drop the least % significant $4$ digits. In the case of a very large (positive or % negative) exponent, we can (and we need to) drop $4$ additional % digits, since the result is of order $10^4$. Naively, one would @@ -613,9 +606,9 @@ % % \subsubsection{Sign, exponent, and special numbers} % -% \begin{macro}[int, EXP]{\@@_exp:w} +% \begin{macro}[int, EXP]{\@@_exp_o:w} % \begin{macrocode} -\cs_new:Npn \@@_exp:w \s_@@ \@@_chk:w #1#2 +\cs_new:Npn \@@_exp_o:w \s_@@ \@@_chk:w #1#2 { \if_case:w #1 \exp_stop_f: \@@_case_return_o:Nw \c_one_fp @@ -655,7 +648,7 @@ \__int_value:w #1 \__int_eval:w \if_int_compare:w #4 < - \c_eight \c_one - \exp_after:wN \@@_add_big_i:wNww + \exp_after:wN \@@_add_big_i_o:wNww \int_use:N \__int_eval:w \c_one - #4 ; 0 {1000}{0000}{0000}{0000} ; #5; \tex_romannumeral:D @@ -1019,12 +1012,12 @@ % \begin{macro}[aux, EXP]{\@@_pow_npos:Nww} % We now know that $a\neq\pm 1$ is a normal number, and $b$ is a % normal number too. We want to compute $\lvert a\rvert^{b} = (\lvert -% x\rvert\cdot 10^{n})^{y\cdot 10^{p}} = \exp((\log\lvert x\rvert + n -% \log 10)\cdot y \cdot 10^{p}) = \exp(z)$. To compute the +% x\rvert\cdot 10^{n})^{y\cdot 10^{p}} = \exp((\ln\lvert x\rvert + n +% \ln(10))\cdot y \cdot 10^{p}) = \exp(z)$. To compute the % exponential accurately, we need to know the digits of $z$ up to the % $16$-th position. Since the exponential of $10^{5}$ is infinite, we % only need at most $21$ digits, hence the fixed point result of -% \cs{@@_ln:w} is precise enough for our needs. Start an integer +% \cs{@@_ln_o:w} is precise enough for our needs. Start an integer % expression for the decimal exponent of $e^{\lvert z\rvert}$. If $z$ % is negative, negate that decimal exponent, and prepare to take the % inverse when converting from the fixed point to the floating point result. @@ -1051,7 +1044,7 @@ % \begin{macro}[aux, EXP]{\@@_pow_npos_aux:Nnww} % The first argument is the conversion function from fixed point to % float. Then comes an exponent and the $4$ brace groups of $x$, -% followed by $b$. Compute $-\log x$. +% followed by $b$. Compute $-\ln(x)$. % \begin{macrocode} \cs_new:Npn \@@_pow_npos_aux:Nnww #1#2#3#4; \s_@@ \@@_chk:w 1#5#6#7; { @@ -1065,10 +1058,10 @@ \cs_new:Npn \@@_pow_exponent:wnN #1; #2 { \if_int_compare:w #2 > \c_zero - \exp_after:wN \@@_pow_exponent:Nwnnnnnn % n\log 10 - (-\log x) + \exp_after:wN \@@_pow_exponent:Nwnnnnnn % n\ln(10) - (-\ln(x)) \exp_after:wN + \else: - \exp_after:wN \@@_pow_exponent:Nwnnnnnn % -( |n|\log 10 + (-\log x) ) + \exp_after:wN \@@_pow_exponent:Nwnnnnnn % -( |n|\ln(10) + (-\ln(x)) ) \exp_after:wN - \fi: #2; #1; @@ -1153,7 +1146,7 @@ \exp_after:wN \@@_pow_neg_neg:w \or: \if_int_compare:w \__int_eval:w #1 / \c_two = \c_one - \@@_invalid_operation:Nnww \c_nan_fp { ^ } #3; #4; + \@@_invalid_operation_o:Nww ^ #3; #4; \tex_romannumeral:D -`0 \exp_after:wN \exp_after:wN \exp_after:wN \@@_use_none_until_s:w @@ -1249,4 +1242,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx index d38c6de8e17..febda1e81b1 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx @@ -35,7 +35,7 @@ %% % %<*driver> -\RequirePackage{l3names} +\RequirePackage{l3bootstrap} \GetIdInfo$Id: l3fp-extended.dtx 2474 2011-06-17 12:54:02Z bruno $ {L3 Floating-point extended precision fixed-points} \documentclass[full]{l3doc} @@ -671,4 +671,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx index 2517236fb21..9813509686d 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx @@ -35,7 +35,7 @@ %% % %<*driver> -\RequirePackage{l3names} +\RequirePackage{l3bootstrap} \GetIdInfo$Id: l3fp-logic.dtx 3504 2012-03-06 06:38:45Z bruno $ {L3 Floating-point conditionals} \documentclass[full]{l3doc} @@ -77,6 +77,20 @@ %<@@=fp> % \end{macrocode} % +% \subsection{Syntax of internal functions} +% +% \begin{itemize} +% \item \cs{@@_compare_npos:nwnw} \Arg{expo_1} \meta{body_1} |;| +% \Arg{expo_2} \meta{body_2} |;| +% \item \cs{@@_max_o:w} \meta{floating point array} +% \item \cs{@@_min_o:w} \meta{floating point array} +% \item \cs{@@_not_o:w} \meta{floating point} +% \item \cs{@@_\string&_o:ww} \meta{floating point} \meta{floating point} +% \item \cs{@@_\string|_o:ww} \meta{floating point} \meta{floating point} +% \item \cs{@@_ternary:NwwN}, \cs{@@_ternary_i:NwwN}, +% \cs{@@_ternary_ii:NwwN} have to be understood. +% \end{itemize} +% % \subsection{Existence test} % % \begin{macro}[pTF]{\fp_if_exist:N, \fp_if_exist:c} @@ -95,44 +109,91 @@ % % \subsection{Comparison} % -% \begin{macro}[int, EXP]{\@@_compare:ww} -% \begin{macro}[aux, EXP] -% { -% \@@_compare_nan:w, \@@_compare_mantissa:ww, -% \@@_compare_mantissa:nnnnnnnn -% } -% \begin{syntax} -% \cs{@@_compare:ww} \meta{X} |;| \meta{Y} |;| -% \end{syntax} +% \begin{macro}[pTF, EXP]{\fp_compare:n} +% \begin{macro}[aux, EXP]{\@@_compare_return:w} +% Within floating point expressions, comparison operators are treated +% as operations, so we evaluate |#1|, then compare with $0$. +% \begin{macrocode} +\prg_new_conditional:Npnn \fp_compare:n #1 { p , T , F , TF } + { + \exp_after:wN \@@_compare_return:w + \tex_romannumeral:D -`0 \@@_parse:n {#1} + } +\cs_new:Npn \@@_compare_return:w \s_@@ \@@_chk:w #1#2; + { + \if_meaning:w 0 #1 + \prg_return_false: + \else: + \prg_return_true: + \fi: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[pTF, EXP]{\fp_compare:nNn} +% \begin{macro}[aux, EXP]{\@@_compare_aux:wn} +% Evaluate |#1| and |#3|, using an auxiliary to expand both, and feed +% the two floating point numbers swapped to \cs{@@_compare_back:ww}, +% defined below. Compare the result with |`#2-`=|, which is $-1$ for +% |<|, $0$ for |=|, $1$ for |>| and $2$ for |?|. +% \begin{macrocode} +\prg_new_conditional:Npnn \fp_compare:nNn #1#2#3 { p , T , F , TF } + { + \if_int_compare:w + \exp_after:wN \@@_compare_aux:wn + \tex_romannumeral:D -`0 \@@_parse:n {#1} {#3} + = \__int_eval:w `#2 - `= \__int_eval_end: + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +\cs_new:Npn \@@_compare_aux:wn #1; #2 + { + \exp_after:wN \@@_compare_back:ww + \tex_romannumeral:D -`0 \@@_parse:n {#2} #1; + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[aux, EXP]{\@@_compare_back:ww, \@@_compare_nan:w} +% \begin{quote} +% \cs{@@_compare_back:ww} \meta{y} |;| \meta{x} |;| +% \end{quote} % Expands (in the same way as \cs{int_eval:n}) to $-1$ if $x<y$, $0$ -% if $x=y$, $1$ if $x>y$, and $2$ otherwise (denoted as $x?y$). A -% trick that will later be useful is that the character codes of |<|, -% |=|, |>| and |?| are contiguous, and in the same order as the return -% codes of \cs{@@_compare:ww}. +% if $x=y$, $1$ if $x>y$, and $2$ otherwise (denoted as $x?y$). If +% either operand is \texttt{nan}, stop the comparison with +% \cs{@@_compare_nan:w} returning $2$. If $x$ is negative, swap the +% outputs $1$ and $-1$ (\emph{i.e.}, $>$ and $<$); we can henceforth +% assume that $x\geq 0$. If $y\geq 0$, and they have the same type, +% either they are normal and we compare them with +% \cs{@@_compare_npos:nwnw}, or they are equal. If $y\geq 0$, but of +% a different type, the highest type is a larger number. Finally, if +% $y\leq 0$, then $x>y$, unless both are zero. % \begin{macrocode} -\cs_new:Npn \@@_compare:ww \s_@@ \@@_chk:w #1#2#3; \s_@@ \@@_chk:w #4#5#6; +\cs_new:Npn \@@_compare_back:ww + \s_@@ \@@_chk:w #1 #2 #3; + \s_@@ \@@_chk:w #4 #5 #6; { \__int_value:w \if_meaning:w 3 #1 \exp_after:wN \@@_compare_nan:w \fi: \if_meaning:w 3 #4 \exp_after:wN \@@_compare_nan:w \fi: - \if_meaning:w 2 #2 - \fi: + \if_meaning:w 2 #5 - \fi: \if_meaning:w #2 #5 \if_meaning:w #1 #4 \if_meaning:w 1 #1 - \@@_compare_mantissa:ww #3; #6; + \@@_compare_npos:nwnw #6; #3; \else: 0 \fi: \else: - \if_int_compare:w #1 < #4 - \fi: 1 + \if_int_compare:w #4 < #1 - \fi: 1 \fi: \else: - \if_meaning:w 0 #1 - \if_meaning:w 0 #4 - 0 - \else: - 1 - \fi: + \if_int_compare:w #1#4 = \c_zero + 0 \else: 1 \fi: @@ -140,7 +201,26 @@ \exp_stop_f: } \cs_new:Npn \@@_compare_nan:w #1 \exp_stop_f: { \c_two } -\cs_new:Npn \@@_compare_mantissa:ww #1#2; #3#4; +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int, EXP]{\@@_compare_npos:nwnw} +% \begin{macro}[aux, EXP]{\@@_compare_mantissa:nnnnnnnn} +% \begin{quote} +% \cs{@@_compare_npos:nwnw} +% \Arg{expo_1} \meta{body_1} |;| +% \Arg{expo_2} \meta{body_2} |;| +% \end{quote} +% Within an \cs{__int_value:w} \ldots{} \cs{exp_stop_f:} construction, +% this expands to $0$ if the two numbers are equal, $-1$ if the first +% is smaller, and $1$ if the first is bigger. First compare the +% exponents: the larger one denotes the larger number. If they are +% equal, we must compare mantissas. If both the first $8$ digits and +% the next $8$ digits coincide, the numbers are equal. If only the +% first $8$ digits coincide, the next $8$ decide. Otherwise, the +% first $8$ digits are compared. +% \begin{macrocode} +\cs_new:Npn \@@_compare_npos:nwnw #1#2; #3#4; { \if_int_compare:w #1 = #3 \exp_stop_f: \@@_compare_mantissa:nnnnnnnn #2 #4 @@ -150,83 +230,114 @@ } \cs_new:Npn \@@_compare_mantissa:nnnnnnnn #1#2#3#4#5#6#7#8 { - \if_int_compare:w #1 = #5 \exp_stop_f: - \if_int_compare:w #2 = #6 \exp_stop_f: - \if_int_compare:w #3 = #7 \exp_stop_f: - \if_int_compare:w #4 = #8 \exp_stop_f: - 0 - \else: - \if_int_compare:w #4 < #8 - \fi: 1 - \fi: - \else: - \if_int_compare:w #3 < #7 - \fi: 1 - \fi: + \if_int_compare:w #1#2 = #5#6 \exp_stop_f: + \if_int_compare:w #3#4 = #7#8 \exp_stop_f: + 0 \else: - \if_int_compare:w #2 < #6 - \fi: 1 + \if_int_compare:w #3#4 < #7#8 - \fi: 1 \fi: \else: - \if_int_compare:w #1 < #5 - \fi: 1 + \if_int_compare:w #1#2 < #5#6 - \fi: 1 \fi: } % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}[pTF, EXP]{\fp_compare:nNn} -% \begin{macro}[aux, EXP]{\@@_compare_aux:wn} -% Evaluate |#1| and |#3|, using an auxiliary to expand both, in the -% correct order. Then compare this to |`#2-`=|, which is $-1$ for -% |<|, $0$ for |=|, $1$ for |>| and $2$ for |?|. +% \subsection{Extrema} +% +% \begin{macro}[int, EXP]{\@@_max_o:w, \@@_min_o:w} +% The maximum (minimum) of an array of floating point numbers is +% computed by reading them sequentially, keeping track of the largest +% (smallest) number found so far. We start with $-\infty$ ($\infty$) +% since every number is larger (smaller) than that. The weird fp-like +% trailing marker breaks the loop correctly: see the precise +% definition of \cs{@@_minmax_loop:Nww}. % \begin{macrocode} -\prg_new_conditional:Npnn \fp_compare:nNn #1#2#3 { p , T , F , TF } +\cs_new:Npn \@@_max_o:w #1 @ { - \if_int_compare:w - \exp_after:wN \@@_compare_aux:wn - \tex_romannumeral:D -`0 \@@_parse:n {#3} {#1} - = \__int_eval:w `#2 - `= \__int_eval_end: - \prg_return_true: - \else: - \prg_return_false: - \fi: + \exp_after:wN \@@_minmax_loop:Nww + \exp_after:wN \c_minus_one + \c_minus_inf_fp + #1 + \s_@@ \@@_chk:w { 3 \@@_minmax_break_o:w } ; } -\cs_new:Npn \@@_compare_aux:wn #1; #2 +\cs_new:Npn \@@_min_o:w #1 @ { - \exp_after:wN \@@_compare:ww - \tex_romannumeral:D -`0 \@@_parse:n {#2} #1; + \exp_after:wN \@@_minmax_loop:Nww + \exp_after:wN \c_one + \c_inf_fp + #1 + \s_@@ \@@_chk:w { 3 \@@_minmax_break_o:w } ; } % \end{macrocode} % \end{macro} -% \end{macro} % -% \begin{macro}[EXP,pTF]{\fp_compare:n} -% \begin{macro}[aux,EXP]{\@@_compare_aux:w} -% For floating points the comparison operators are treated as -% operations, so we simply evaluate then compare with \cs{c_zero_fp}. +% \begin{macro}[aux, EXP]{\@@_minmax_loop:Nww} +% The first argument is $-1$ or $1$ to denote the case where the +% currently largest (smallest) number found (first floating point +% argument) should be replaced by the new number (second floating +% point argument). If the new number is \texttt{nan}, keep that as +% the extremum, unless that extremum is already a \texttt{nan}. +% Otherwise, compare the two numbers. If the new number is larger (in +% the case of |max|) or smaller (in the case of |min|), the test +% yields \texttt{true}, and we keep the second number as a new +% maximum; otherwise we keep the first number. Then loop. % \begin{macrocode} -\prg_new_conditional:Npnn \fp_compare:n #1 { p , T , F , TF } - { - \exp_after:wN \@@_compare_aux:w - \tex_romannumeral:D -`0 \@@_parse:n {#1} - } -\cs_new:Npn \@@_compare_aux:w \s_@@ \@@_chk:w #1#2; +\cs_new:Npn \@@_minmax_loop:Nww + #1 \s_@@ \@@_chk:w #2#3; \s_@@ \@@_chk:w #4#5; { - \if_meaning:w 0 #1 - \prg_return_false: + \if_meaning:w 3 #4 + \if_meaning:w 3 #2 + \@@_minmax_i:ww + \else: + \@@_minmax_ii:ww + \fi: \else: - \prg_return_true: + \if_int_compare:w + \@@_compare_back:ww + \s_@@ \@@_chk:w #4#5; + \s_@@ \@@_chk:w #2#3; + = #1 + \@@_minmax_ii:ww + \else: + \@@_minmax_i:ww + \fi: \fi: + \@@_minmax_loop:Nww #1 + \s_@@ \@@_chk:w #2#3; + \s_@@ \@@_chk:w #4#5; } % \end{macrocode} % \end{macro} +% +% \begin{macro}[aux, EXP]{\@@_minmax_i:ww, \@@_minmax_ii:ww} +% Keep the first/second number, and remove the other. +% \begin{macrocode} +\cs_new:Npn \@@_minmax_i:ww #1 \fi: \fi: #2 \s_@@ #3 ; \s_@@ #4; + { \fi: \fi: #2 \s_@@ #3 ; } +\cs_new:Npn \@@_minmax_ii:ww #1 \fi: \fi: #2 \s_@@ #3 ; + { \fi: \fi: #2 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[aux, EXP]{\@@_minmax_break_o:w} +% This function is called from within an \cs{if_meaning:w} test. Skip +% to the end of the tests, close the current test with \cs{fi:}, clean +% up, and return the appropriate number with one post-expansion. +% \begin{macrocode} +\cs_new:Npn \@@_minmax_break_o:w #1 \fi: \fi: #2 \s_@@ #3; #4; + { \fi: \@@_exp_after_o:w \s_@@ #3; } +% \end{macrocode} % \end{macro} % % \subsection{Boolean operations} % -% \begin{macro}[int, EXP]{\@@_not:w} +% \begin{macro}[int, EXP]{\@@_not_o:w} % Return \texttt{true} or \texttt{false}, with two expansions, one to % exit the conditional, and one to please \pkg{l3fp-parse}. % \begin{macrocode} -\cs_new:Npn \@@_not:w \s_@@ \@@_chk:w #1#2; +\cs_new:Npn \@@_not_o:w \s_@@ \@@_chk:w #1#2; { \if_meaning:w 0 #1 \exp_after:wN \exp_after:wN \exp_after:wN \c_one_fp @@ -247,23 +358,34 @@ % \cs{@@_\&_o:ww}, inserting an extra argument, \cs{else:}, before % \cs{s_@@}. In all cases, expand after the floating point number. % \begin{macrocode} -\cs_new:cpn { @@_ \iow_char:N \& _o:ww } #1 \s_@@ \@@_chk:w #2#3; - { - \if_meaning:w 0 #2 #1 - \@@_and_return:wNw \s_@@ \@@_chk:w #2#3; - \fi: - \@@_exp_after_o:w - } -\cs_new_nopar:cpx { @@_ \iow_char:N \| _o:ww } - { \exp_not:c { @@_ \iow_char:N \& _o:ww } \exp_not:N \else: } +\group_begin: + \char_set_catcode_letter:N & + \char_set_catcode_letter:N | + \cs_new:Npn \@@_&_o:ww #1 \s_@@ \@@_chk:w #2#3; + { + \if_meaning:w 0 #2 #1 + \@@_and_return:wNw \s_@@ \@@_chk:w #2#3; + \fi: + \@@_exp_after_o:w + } + \cs_new_nopar:Npn \@@_|_o:ww { \@@_&_o:ww \else: } +\group_end: \cs_new:Npn \@@_and_return:wNw #1; \fi: #2#3; { \fi: #2 #1; } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % +% \subsection{Ternary operator} +% +%^^A todo: understand and optimize. % \begin{macro}[int, EXP] % {\@@_ternary:NwwN, \@@_ternary_i:NwwN, \@@_ternary_ii:NwwN} +% \begin{macro}[aux, EXP] +% { +% \@@_ternary_loop_break:w, \@@_ternary_loop:Nw, +% \@@_ternary_map_break:, \@@_ternary_break_point:n +% } % The first function receives the test and the true branch of the |?:| % ternary operator. It returns the true branch, unless the test % branch is zero. In that case, the function returns a very specific @@ -271,7 +393,6 @@ % function, and the false branch. It returns the previous input, % unless that is the special \texttt{nan}, in which case we return the % false branch. -%^^A todo: optimize. % \begin{macrocode} \cs_new:Npn \@@_ternary:NwwN #1 #2@ #3@ #4 { @@ -288,7 +409,8 @@ \@@_parse_until:Nw \c_two \@@_parse_expand:w \else: - \@@_error:n { Missing~':'~clause~for~'?:'. } + \__msg_kernel_expandable_error:nnnn + { kernel } { fp-missing } { : } { ~for~?: } \exp_after:wN \@@_parse_until_test:NwN \exp_after:wN #1 \tex_romannumeral:D -`0 @@ -328,58 +450,6 @@ } % \end{macrocode} % \end{macro} -% -% \begin{macro}[int, EXP]{\@@_max:w, \@@_min:w} -% \begin{macrocode} -\cs_new:Npn \@@_max:w #1@ - { - \exp_after:wN \@@_minmax_loop:Nww - \exp_after:wN \c_minus_one - \c_minus_inf_fp - #1 - \s_@@ \@@_chk:w { 3 \@@_minmax_break:w } ; - } -\cs_new:Npn \@@_min:w #1@ - { - \exp_after:wN \@@_minmax_loop:Nww - \exp_after:wN \c_one - \c_inf_fp - #1 - \s_@@ \@@_chk:w { 3 \@@_minmax_break:w } ; - } -\cs_new:Npn \@@_minmax_loop:Nww - #1 \s_@@ \@@_chk:w #2#3; \s_@@ \@@_chk:w #4#5; - { - \if_meaning:w 3 #4 - \if_meaning:w 3 #2 - \@@_minmax_i:ww - \else: - \@@_minmax_ii:ww - \fi: - \else: - \if_int_compare:w \@@_compare:ww \s_@@ \@@_chk:w #2#3; - \s_@@ \@@_chk:w #4#5; = #1 - \@@_minmax_ii:ww - \else: - \@@_minmax_i:ww - \fi: - \fi: - \@@_minmax_loop:Nww #1 - \s_@@ \@@_chk:w #2#3; - \s_@@ \@@_chk:w #4#5; - } -\cs_new:Npn \@@_minmax_i:ww - #1 \@@_minmax_loop:Nww #2 \s_@@ #3; \s_@@ #4; - { #1 \@@_minmax_loop:Nww #2 \s_@@ #3; } -\cs_new:Npn \@@_minmax_ii:ww - #1 \@@_minmax_loop:Nww #2 \s_@@ #3; \s_@@ #4; - { #1 \@@_minmax_loop:Nww #2 \s_@@ #4; } -\cs_new:Npn \@@_minmax_break:w #1 \@@_minmax_loop:Nww #2 #3; #4; - { - \fi: - \@@_exp_after_o:w #3; - } -% \end{macrocode} % \end{macro} % % \begin{macrocode} @@ -390,4 +460,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-old.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-old.dtx index b195f766d52..63895efcaae 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-old.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-old.dtx @@ -35,8 +35,8 @@ %% % %<*driver> -\RequirePackage{l3names} -\GetIdInfo$Id: l3fp-old.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3fp-old.dtx 4082 2012-08-12 12:14:17Z bruno $ {L3 Experimental floating-points (old)} \documentclass[full]{l3doc} \begin{document} @@ -120,11 +120,17 @@ % \fp_abs:N , \fp_abs:c , \fp_gabs:N , \fp_gabs:c , % \fp_neg:N , \fp_neg:c , \fp_gneg:N , \fp_gneg:c , % } +% \begin{macro}[aux]{\@@_abs:NNN} +% Simply expand the floating point variable to feed it to +% \cs{@@_abs_o:w} or \cs{@@_neg_o:w}, expanded within an expanding +% token list assignment. The \cs{prg_do_nothing:} is not necessary, +% but it reminds us moe clearly that \cs{@@_abs_o:w} and +% \cs{@@_neg_o:w} expand after their result. % \begin{macrocode} -\cs_new_protected_nopar:Npn \fp_abs:N { \@@_abs:NNN \tl_set:Nx \@@_abs:w } -\cs_new_protected_nopar:Npn \fp_gabs:N { \@@_abs:NNN \tl_gset:Nx \@@_abs:w } -\cs_new_protected_nopar:Npn \fp_neg:N { \@@_abs:NNN \tl_set:Nx \@@_neg:w } -\cs_new_protected_nopar:Npn \fp_gneg:N { \@@_abs:NNN \tl_gset:Nx \@@_neg:w } +\cs_new_protected_nopar:Npn \fp_abs:N { \@@_abs:NNN \tl_set:Nx \@@_abs_o:w } +\cs_new_protected_nopar:Npn \fp_gabs:N { \@@_abs:NNN \tl_gset:Nx \@@_abs_o:w } +\cs_new_protected_nopar:Npn \fp_neg:N { \@@_abs:NNN \tl_set:Nx \@@_neg_o:w } +\cs_new_protected_nopar:Npn \fp_gneg:N { \@@_abs:NNN \tl_gset:Nx \@@_neg_o:w } \cs_new_protected:Npn \@@_abs:NNN #1#2#3 { #1 #3 { \exp_after:wN #2 #3 \prg_do_nothing: } } \cs_generate_variant:Nn \fp_abs:N { c } @@ -133,6 +139,7 @@ \cs_generate_variant:Nn \fp_gneg:N { c } % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macro} % { @@ -149,7 +156,8 @@ \cs_new_protected_nopar:Npn \fp_gdiv:Nn { \@@_mul:NNNn \fp_gset:Nn / } \cs_new_protected_nopar:Npn \fp_pow:Nn { \@@_mul:NNNn \fp_set:Nn ^ } \cs_new_protected_nopar:Npn \fp_gpow:Nn { \@@_mul:NNNn \fp_gset:Nn ^ } -\cs_new_protected:Npn \@@_mul:NNNn #1#2#3#4 { #1 #3 { #3 #2 (#4) } } +\cs_new_protected:Npn \@@_mul:NNNn #1#2#3#4 + { #1 #3 { #3 #2 \@@_parse:n {#4} } } \cs_generate_variant:Nn \fp_mul:Nn { c } \cs_generate_variant:Nn \fp_gmul:Nn { c } \cs_generate_variant:Nn \fp_div:Nn { c } @@ -170,9 +178,8 @@ % } % \begin{macro}[aux] % {\@@_assign_to:nNNNn, \@@_assign_to_i:wNNNn, \@@_assign_to_ii:NnNNN} -% Here, an added twist -% is that each value computed by these expensive unary operations is -% stored as a constant floating point number. +% Here, an added twist is that each value computed by these expensive +% unary operations is stored as a constant floating point number. % \begin{macrocode} \cs_set_protected:Npn \@@_tmp:w #1#2#3#4#5 { @@ -181,11 +188,11 @@ \cs_generate_variant:Nn #1 { c } \cs_generate_variant:Nn #2 { c } } -\@@_tmp:w \fp_exp:Nn \fp_gexp:Nn \@@_exp:w {exp} \@@_assign_to:nNNNn -\@@_tmp:w \fp_ln:Nn \fp_gln:Nn \@@_ln:w {ln } \@@_assign_to:nNNNn -\@@_tmp:w \fp_sin:Nn \fp_gsin:Nn \@@_sin:w {sin} \@@_assign_to:nNNNn -\@@_tmp:w \fp_cos:Nn \fp_gcos:Nn \@@_cos:w {cos} \@@_assign_to:nNNNn -\@@_tmp:w \fp_tan:Nn \fp_gtan:Nn \@@_tan:w {tan} \@@_assign_to:nNNNn +\@@_tmp:w \fp_exp:Nn \fp_gexp:Nn \@@_exp_o:w {exp} \@@_assign_to:nNNNn +\@@_tmp:w \fp_ln:Nn \fp_gln:Nn \@@_ln_o:w {ln } \@@_assign_to:nNNNn +\@@_tmp:w \fp_sin:Nn \fp_gsin:Nn \@@_sin_o:w {sin} \@@_assign_to:nNNNn +\@@_tmp:w \fp_cos:Nn \fp_gcos:Nn \@@_cos_o:w {cos} \@@_assign_to:nNNNn +\@@_tmp:w \fp_tan:Nn \fp_gtan:Nn \@@_tan_o:w {tan} \@@_assign_to:nNNNn \cs_new_protected:Npn \@@_assign_to:nNNNn #1#2#3#4#5 { \exp_after:wN \@@_assign_to_i:wNNNn @@ -194,7 +201,7 @@ \cs_new_protected:Npn \@@_assign_to_i:wNNNn \s_@@ \@@_chk:w #1#2#3; #4 { \exp_args:Nc \@@_assign_to_ii:NnNNN - { c_@@_ #4 ( #2 \if_meaning:w 1 #1 #3 \fi: ) _fp } + { c_@@_ #4 [ #1 # 2 \if_meaning:w 1 #1 #3 \fi: ] _fp } { #1#2#3 } } \cs_new_protected:Npn \@@_assign_to_ii:NnNNN #1#2#3#4#5 @@ -207,14 +214,13 @@ % \end{macro} % \end{macro} % -% \begin{macro}[pTF, EXP]{\fp_compare:NNN} +% \begin{macro}[TF]{\fp_compare:NNN} % Comparisons used to be easier between floating points stored in % variables. No more. % \begin{macrocode} \cs_new_protected_nopar:Npn \fp_compare:NNNTF { \fp_compare:nNnTF } \cs_new_protected_nopar:Npn \fp_compare:NNNT { \fp_compare:nNnT } \cs_new_protected_nopar:Npn \fp_compare:NNNF { \fp_compare:nNnF } -\cs_new_protected_nopar:Npn \fp_compare_p:NNN { \fp_compare_p:nNn } % \end{macrocode} % \end{macro} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx index 11ec4e11b54..f74c2cf0a92 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx @@ -35,8 +35,8 @@ %% % %<*driver> -\RequirePackage{l3names} -\GetIdInfo$Id: l3fp-parse.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3fp-parse.dtx 4081 2012-08-12 11:06:18Z bruno $ {L3 Floating-point expression parsing} \documentclass[full]{l3doc} \begin{document} @@ -315,10 +315,10 @@ % (essentially) to % \begin{quote} % \cs{until} \meta{prec} -% \cs{@@_mul_o:ww} \meta{floating point} \meta{floating point_2} +% \cs{@@_*_o:ww} \meta{floating point} \meta{floating point_2} % \cs{tex_romannumeral:D} \texttt{-`0} \cs{infix_?} \meta{prec} % \end{quote} -% making \TeX{} expand \cs{@@_mul_o:ww} before \cs{until}. As +% making \TeX{} expand \cs{@@_*_o:ww} before \cs{until}. As % implemented in \pkg{l3fp-basics}, this operation expands what follows % its result exactly once. This triggers \cs{tex_romannumeral:D}, % which fully expands \cs{infix_?} \meta{prec}. This compares @@ -333,7 +333,7 @@ % \begin{itemize} % \item a test function, \cs{infix_*}, which conditionally continues % the calculation or waits to be hit again by expansion; -% \item a function \fpOperation{*} (notation for \cs{@@_mul_o:ww}) +% \item a function \fpOperation{*} (notation for \cs{@@_*_o:ww}) % which performs the actual calculation; % \item an integer, \fpPrecedence{*}, which encodes the precedence of % the operator. @@ -976,7 +976,7 @@ } \s_@@ #2 { - \@@_error:n { Premature~end~in~fp~expression. } + \__msg_kernel_expandable_error:nn { kernel } { fp-early-end } \exp_after:wN \c_nan_fp \tex_romannumeral:D -`0 \@@_parse_infix:NN #1 @@ -984,7 +984,8 @@ } \s_@@_mark { - \@@_error:n { Erroneous~variable~#2 used! } + \__msg_kernel_expandable_error:nnn + { kernel } { bad-variable } {#2} \exp_after:wN \c_nan_fp \tex_romannumeral:D -`0 \exp_after:wN \@@_parse_infix:NN @@ -1054,7 +1055,8 @@ { \cs_if_exist_use:cF { @@_parse_word_#2:N } { - \__msg_expandable_error:n { Unknown~word~#2. } + \__msg_kernel_expandable_error:nnn + { kernel } { unknown-fp-word } {#2} \exp_after:wN \c_nan_fp \tex_romannumeral:D -`0 \@@_parse_infix:NN @@ -1074,13 +1076,15 @@ { \cs_if_exist:cTF { @@_parse_infix_#1:N } { - \@@_error:n { Missing~number~before~'#1'. } + \__msg_kernel_expandable_error:nnn + { kernel } { fp-missing-number } {#1} \exp_after:wN \c_nan_fp \tex_romannumeral:D -`0 \@@_parse_infix:NN #3 #1 } { - \@@_error:n { Unknown~symbol~#1~ignored. } + \__msg_kernel_expandable_error:nnn + { kernel } { fp-unknown-symbol } {#1} \@@_parse_operand:Nw #3 } } @@ -1653,10 +1657,14 @@ \if_catcode:w \tex_relax:D #1 \if_meaning:w \tex_relax:D #1 \if_int_compare:w \pdftex_strcmp:D { \s_@@ } { #1 } = \c_zero - 0 \@@_error:n { Cannot~use~floating~point~after~'e'. } + 0 + \__msg_kernel_expandable_error:nnn + { kernel } { fp-after-e } { floating~point~ } \prg_return_true: \else: - 0 \@@_error:n { Erroneous~variable~#1 used. } + 0 + \__msg_kernel_expandable_error:nnn + { kernel } { bad-variable } {#1} \prg_return_false: \fi: \else: @@ -1665,12 +1673,16 @@ = \c_zero \__int_value:w #1 \else: - 0 \@@_error:n { Cannot~use~a~dimension~(#1)~after~'e'. } + 0 + \__msg_kernel_expandable_error:nnn + { kernel } { fp-after-e } { dimension~#1 } \fi: \prg_return_false: \fi: \else: - 0 \@@_error:n { Missing~exponent~after~'e'. } + 0 + \__msg_kernel_expandable_error:nnn + { kernel } { fp-missing } { exponent } \prg_return_true: \fi: } @@ -1678,7 +1690,7 @@ % \end{macro} % % ^^A begin[todo] -% ^^A todo: \@@_sin:Nn should first _set, then \@@_sin:w, +% ^^A todo: \@@_sin:Nn should first _set, then \@@_sin_o:w, % ^^A both for speed, and error reporting. % ^^A todo: word 'e' == 'invalid syntax', word 'E' == "use 'e' instead" % @@ -1961,7 +1973,7 @@ \cs_new:Npn \@@_parse_infix_check:NNN #1#2#3 { \if_meaning:w \tex_relax:D #1 - \__msg_expandable_error:n { Missing~*~inserted. } + \__msg_kernel_expandable_error:nnn { kernel } { fp-missing } { * } \exp_after:wN \@@_parse_infix_*:N \exp_after:wN #2 \exp_after:wN #3 @@ -1997,7 +2009,7 @@ % % \begin{macro}[int, EXP] % {\@@_parse_apply_unary_array:NNwN, \@@_parse_apply_unary:NNwN} -% Here, |#2| is \emph{e.g.}, \cs{@@_neg_@@:w}, and expands once after the +% Here, |#2| is \emph{e.g.}, \cs{@@_neg_o:w}, and expands once after the % calculation.\footnote{Bruno: explain.} The argument |#3| may be an % array, so either we map through all its items, or we feed all items % at once to the custom function. @@ -2013,7 +2025,7 @@ \tex_romannumeral:D -`0 #4 #1 } \cs_new:Npn \@@_parse_unary_type:N #1 - { \@@_type_from_scan:N #1 :w \cs_end: #1 } + { \@@_type_from_scan:N #1 _o:w \cs_end: #1 } % \end{macrocode} % \end{macro} % @@ -2106,7 +2118,6 @@ % \begin{macro}[int, EXP] % { % \@@_parse_word_max:N , \@@_parse_word_min:N , -% \@@_parse_word_mod:N , % } % Those functions are also unary, but need to mix all of their % arguments together. @@ -2122,9 +2133,8 @@ \@@_parse_until:Nw \c_sixteen \@@_parse_expand:w } } -\@@_tmp:w \@@_parse_word_max:N \@@_max:w -\@@_tmp:w \@@_parse_word_min:N \@@_min:w - % \@@_tmp:w \@@_parse_word_mod:N \@@_mod:w %^^A todo: not implemented! +\@@_tmp:w \@@_parse_word_max:N \@@_max_o:w +\@@_tmp:w \@@_parse_word_min:N \@@_min_o:w % \end{macrocode} % \end{macro} % @@ -2159,7 +2169,8 @@ \@@_round:Nwn #2 #3 {0} \tex_romannumeral:D \or: \@@_round:Nww #2 #3 \tex_romannumeral:D \else: - \@@_error:n { round()~expects~1~or~2~arguments. } + \__msg_kernel_expandable_error:nnnnn + { kernel } { fp-num-args } { round() } { 1 } { 2 } \exp_after:wN \c_nan_fp \tex_romannumeral:D \fi: -`0 #4 #1 @@ -2229,7 +2240,7 @@ \tex_romannumeral:D \@@_parse_expand:w } { - \@@_error:n { Missing~')'~inserted. } + \__msg_kernel_expandable_error:nnn { kernel } { fp-missing } { ) } #2 @ \@@_parse_stop_until:N #3 } } @@ -2383,7 +2394,7 @@ % \@@_parse_infix_excl_aux:NN, % \@@_parse_infix_excl_error:, % \@@_infix_compare:N, -% \@@_parse_compare:NNNNNw, +% \@@_parse_compare:NNNNNNw, % \@@_parse_compare_expand:NNNNNw, % \@@_parse_compare_end:NNNN, % \@@_compare:wNNNNw, @@ -2411,50 +2422,44 @@ } \cs_new:Npn \@@_parse_infix_excl_aux:NN #1#2 { - \if_catcode:w \tex_relax:D #2 - \@@_parse_infix_excl_error: - \else: - \if_int_compare:w `#2 > `? \exp_stop_f: - \@@_parse_infix_excl_error: - \else: - \if_int_compare:w `#2 < `< \exp_stop_f: - \@@_parse_infix_excl_error: - \fi: - \fi: - \fi: \@@_infix_compare:N #1 \c_zero_fp \c_one_fp \c_one_fp \c_one_fp \c_one_fp #2 } \cs_new:Npn \@@_parse_infix_excl_error: - { \__msg_expandable_error:n { Missing~relation~symbol~after~'!'. } } + { + \__msg_kernel_expandable_error:nnnn + { kernel } { fp-missing } { = } { ~after~!. } + } \cs_new:Npn \@@_infix_compare:N #1 { \if_int_compare:w #1 < \c_seven - \exp_after:wN \@@_parse_compare:NNNNNw + \exp_after:wN \@@_parse_compare:NNNNNNw + \exp_after:wN \@@_parse_infix_excl_error: \else: \exp_after:wN @ \exp_after:wN \@@_parse_stop_until:N \exp_after:wN \@@_infix_compare:N \fi: } -\cs_new:Npn \@@_parse_compare:NNNNNw #1#2#3#4#5#6 +\cs_new:Npn \@@_parse_compare:NNNNNNw #1#2#3#4#5#6#7 { \if_case:w - \if_catcode:w \tex_relax:D #6 + \if_catcode:w \tex_relax:D #7 \c_minus_one \else: - \__int_eval:w `#6 - `< \__int_eval_end: + \__int_eval:w `#7 - `< \__int_eval_end: \fi: - \@@_parse_compare_expand:NNNNNw #1#1#3#4#5 - \or: \@@_parse_compare_expand:NNNNNw #1#2#1#4#5 - \or: \@@_parse_compare_expand:NNNNNw #1#2#3#1#5 - \or: \@@_parse_compare_expand:NNNNNw #1#2#3#4#1 - \else: \@@_parse_compare_end:NNNN #2#3#4#5#6 + \@@_parse_compare_expand:NNNNNw #2#2#4#5#6 + \or: \@@_parse_compare_expand:NNNNNw #2#3#2#5#6 + \or: \@@_parse_compare_expand:NNNNNw #2#3#4#2#6 + \or: \@@_parse_compare_expand:NNNNNw #2#3#4#5#2 + \else: #1 \@@_parse_compare_end:NNNN #3#4#5#6#7 \fi: } \cs_new:Npn \@@_parse_compare_expand:NNNNNw #1#2#3#4#5 { - \exp_after:wN \@@_parse_compare:NNNNNw + \exp_after:wN \@@_parse_compare:NNNNNNw + \exp_after:wN \prg_do_nothing: \exp_after:wN #1 \exp_after:wN #2 \exp_after:wN #3 @@ -2482,7 +2487,7 @@ \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN - \if_case:w \@@_compare:ww #2 #7 \exp_stop_f: + \if_case:w \@@_compare_back:ww #7 #2 \exp_stop_f: #4 \or: #5 \or: #6 @@ -2515,7 +2520,8 @@ \cs_new:Npn \@@_parse_infix_::N #1 { \if_int_compare:w #1 < \c_three - \__msg_expandable_error:n { Missing~'?'~inserted~for~'?:'. } + \__msg_kernel_expandable_error:nnnn + { kernel } { fp-missing } { ? } { ~for~?: } \exp_after:wN @ \exp_after:wN \@@_ternary_ii:NwwN \tex_romannumeral:D @@ -2541,7 +2547,7 @@ \cs_new:Npn \@@_parse_infix_):N #1 { \if_int_compare:w #1 < \c_zero - \@@_error:n { Extra~')'~ignored. } + \__msg_kernel_expandable_error:nnn { kernel } { fp-extra } { ) } \exp_after:wN \@@_parse_infix:NN \exp_after:wN #1 \tex_romannumeral:D \exp_after:wN \@@_parse_expand:w @@ -2583,13 +2589,36 @@ { #1 @ \@@_parse_stop_until:N } \cs_new:Npn \@@_parse_infix_comma_gobble:w #1 @ { - \@@_error:n { Unexpected~comma:~extra~arguments~ignored. } + \__msg_kernel_expandable_error:nn { kernel } { fp-extra-comma } @ \@@_parse_stop_until:N } \group_end: % \end{macrocode} % \end{macro} % +% \section{Messages} +% +% \begin{macrocode} +\__msg_kernel_new:nnn { kernel } { unknown-fp-word } + { Unknown~fp~word~#1. } +\__msg_kernel_new:nnn { kernel } { fp-missing } + { Missing~#1~inserted #2. } +\__msg_kernel_new:nnn { kernel } { fp-extra } + { Extra~#1~ignored. } +\__msg_kernel_new:nnn { kernel } { fp-early-end } + { Premature~end~in~fp~expression. } +\__msg_kernel_new:nnn { kernel } { fp-after-e } + { Cannot~use~#1 after~'e'. } +\__msg_kernel_new:nnn { kernel } { fp-missing-number } + { Missing~number~before~'#1'. } +\__msg_kernel_new:nnn { kernel } { fp-unknown-symbol } + { Unknown~symbol~#1~ignored. } +\__msg_kernel_new:nnn { kernel } { fp-extra-comma } + { Unexpected~comma:~extra~arguments~ignored. } +\__msg_kernel_new:nnn { kernel } { fp-num-args } + { #1~expects~between~#2~and~#3~arguments. } +% \end{macrocode} +% % \begin{macrocode} %</initex|package> % \end{macrocode} @@ -2598,4 +2627,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx index 68df5e1ac17..b14d3e1058f 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx @@ -35,7 +35,7 @@ %% % %<*driver> -\RequirePackage{l3names} +\RequirePackage{l3bootstrap} \GetIdInfo$Id: l3fp-round.dtx 3549 2012-03-13 20:54:30Z bruno $ {L3 Floating-point rounding} \documentclass[full]{l3doc} @@ -119,8 +119,6 @@ % \begin{itemize} % \item \cs{@@_round:NNN} \meta{sign} \meta{digit_1} \meta{digit_2} % can expand to \cs{c_zero} or \cs{c_one}. -% \item \cs{@@_round:NNNN} \meta{sign} \meta{digit_1} \meta{digit_2} -% \meta{digit_3} can expand to \cs{c_zero} or \cs{c_one}. % \item \cs{@@_round_s:NNNw} \meta{sign} \meta{digit_1} \meta{digit_2} % \meta{more digits} |;| can expand to |\c_zero ;| or |\c_one ;|. % \item \cs{@@_round_neg:NNN} \meta{sign} \meta{digit_1} \meta{digit_2} @@ -234,27 +232,26 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[int, EXP]{\@@_round:NNNN} +% \begin{macro}[int, EXP]{\@@_round_digit:Nw} % \begin{syntax} -% \cs{@@_round:NNNN} \meta{final sign} \meta{digit} \meta{2d} +% \cs{__int_value:w} \cs{@@_round_digit:Nw} \meta{digit} \meta{intexpr} |;| % \end{syntax} -% Identical to \cs{@@_round_s:NNNw} except for a trailing semicolon. -% \begin{macrocode} -\cs_new:Npn \@@_round:NNNN #1 #2 #3 #4 +% This function should always be called within an \cs{__int_value:w} +% or \cs{__int_eval:w} expansion; it may add an extra +% \cs{__int_eval:w}, which means that the integer or integer +% expression should not be ended with a synonym of \tn{relax}, but +% with a semi-colon for instance. +% \begin{macrocode} +\cs_new:Npn \@@_round_digit:Nw #1 #2; { - \exp_after:wN \@@_round:NNN - \exp_after:wN #1 - \exp_after:wN #2 - \int_use:N \__int_eval:w - \if_int_odd:w 0 \if_meaning:w 0 #3 1 \fi: - \if_meaning:w 5 #3 1 \fi: - \exp_stop_f: - \if_int_compare:w #4 > \c_zero - 1 + - \fi: + \if_int_odd:w \if_meaning:w 0 #1 \c_one \else: + \if_meaning:w 5 #1 \c_one \else: + \c_zero \fi: \fi: + \if_int_compare:w \__int_eval:w #2 > \c_zero + \__int_eval:w \c_one + \fi: - #3 - \__int_eval_end: + \fi: + #1 } % \end{macrocode} % \end{macro} @@ -332,10 +329,7 @@ \cs_new:Npn \@@_round:Nww #1#2 ; #3 ; { \@@_small_int:wTF #3; { \@@_round:Nwn #1#2; } - { - \@@_error:x { {round(x,n)~with~n=} \@@_to_tl:w #3; } - \exp_after:wN \c_nan_fp - } + { \@@_array_invalid_operation_o:nw { round } #2; #3; @ } } \cs_new:Npn \@@_round:Nwn #1 \s_@@ \@@_chk:w #2#3#4; #5 { @@ -421,4 +415,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx index 2e3a5e262ba..f3e3955c1b1 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx @@ -35,7 +35,7 @@ %% % %<*driver> -\RequirePackage{l3names} +\RequirePackage{l3bootstrap} \GetIdInfo$Id: l3fp-traps.dtx 2479 2011-06-19 21:57:25Z bruno $ {L3 Floating-point exception trapping} \documentclass[full]{l3doc} @@ -87,27 +87,27 @@ % % \subsection{Flags} % -% \begin{macro}{\@@_flag_off:n} +% \begin{macro}{\fp_flag_off:n} % Function to turn a flag off. Simply undefine it. % \begin{macrocode} -\cs_new_protected:Npn \@@_flag_off:n #1 +\cs_new_protected:Npn \fp_flag_off:n #1 { \cs_set_eq:cN { l_@@_ #1 _flag_token } \c_undefined:D } % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]{\@@_flag_on:n} +% \begin{macro}[EXP]{\fp_flag_on:n} % Function to turn a flag on expandably: use \TeX{}'s automatic % assignment to \cs{scan_stop:}. % \begin{macrocode} -\cs_new:Npn \@@_flag_on:n #1 +\cs_new:Npn \fp_flag_on:n #1 { \exp_args:Nc \use_none:n { l_@@_ #1 _flag_token } } % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP,pTF]{\@@_if_flag_on:n} +% \begin{macro}[EXP,pTF]{\fp_if_flag_on:n} % Returns true if the flag is on, false otherwise. % \begin{macrocode} -\prg_new_conditional:Npnn \@@_if_flag_on:n #1 { p , T , F , TF } +\prg_new_conditional:Npnn \fp_if_flag_on:n #1 { p , T , F , TF } { \if_cs_exist:w l_@@_ #1 _flag_token \cs_end: \prg_return_true: @@ -150,21 +150,22 @@ % The behaviour when an exception occurs is controlled by the % definitions of the functions % \begin{itemize} -% \item \cs{@@_invalid_operation:Nnw}, -% \item \cs{@@_invalid_operation:Nnww}, -% \item \cs{@@_division_by_zero:Nnw}, -% \item \cs{@@_division_by_zero:Nnww}, +% \item \cs{@@_invalid_operation:nnw}, +% \item \cs{@@_invalid_operation_o:Nww}, +% \item \cs{@@_array_invalid_operation_o:nw}, +% \item \cs{@@_division_by_zero_o:Nnw}, +% \item \cs{@@_division_by_zero_o:NNww}, % \item \cs{@@_overflow:w}, % \item \cs{@@_underflow:w}. % \end{itemize} % Rather than changing them directly, we provide a user interface as -% \cs{@@_trap:nn} \Arg{exception} \Arg{way of trapping}, where the +% \cs{fp_trap:nn} \Arg{exception} \Arg{way of trapping}, where the % \meta{way of trapping} is one of \texttt{error}, \texttt{flag}, or % \texttt{none}. % -% \begin{macro}{\@@_trap:nn} %^^A todo: user command => document +% \begin{macro}{\fp_trap:nn} %^^A todo: user command => document % \begin{macrocode} -\cs_new_protected:Npn \@@_trap:nn #1#2 +\cs_new_protected:Npn \fp_trap:nn #1#2 { \cs_if_exist_use:cF { @@_trap_#1_set_#2: } { @@ -188,6 +189,50 @@ % \@@_trap_invalid_operation_set_none: , % \@@_trap_invalid_operation_set:N , % } +% We provide three types of trapping for invalid operations: either +% produce an error and raise the relevant flag; or only raise the +% flag; or don't even raise the flag. In most cases, the function +% produces as a result its first argument, possibly with +% post-expansion. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \@@_trap_invalid_operation_set_error: + { \@@_trap_invalid_operation_set:N \prg_do_nothing: } +\cs_new_protected_nopar:Npn \@@_trap_invalid_operation_set_flag: + { \@@_trap_invalid_operation_set:N \use_none:nnnnn } +\cs_new_protected_nopar:Npn \@@_trap_invalid_operation_set_none: + { \@@_trap_invalid_operation_set:N \use_none:nnnnnnn } +\cs_new_protected:Npn \@@_trap_invalid_operation_set:N #1 + { + \exp_args:Nno \use:n + { \cs_set:Npn \@@_invalid_operation:nnw ##1##2##3; } + { + #1 + \@@_error:nffn { invalid } {##2} { \@@_to_tl:w ##3; } { } + \fp_flag_on:n { invalid_operation } + ##1 + } + \exp_args:Nno \use:n + { \cs_set:Npn \@@_invalid_operation_o:Nww ##1##2; ##3; } + { + #1 + \@@_error:nffn { invalid-ii } + { \@@_to_tl:w ##2; } { \@@_to_tl:w ##3; } {##1} + \fp_flag_on:n { invalid_operation } + \exp_after:wN \c_nan_fp + } + \exp_args:Nno \use:n + { \cs_set:Npn \@@_array_invalid_operation_o:nw ##1##2@ } + { + #1 + \@@_error:nffn { invalid } + {##1} { \@@_array_to_clist:w ##2 @ } { } + \fp_flag_on:n { invalid_operation } + \exp_after:wN \c_nan_fp + } + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}[aux] % { % \@@_trap_division_by_zero_set_error: , @@ -195,64 +240,40 @@ % \@@_trap_division_by_zero_set_none: , % \@@_trap_division_by_zero_set:N , % } -% \begin{macro}[aux]{\@@_trap_invalid_operation_set:Nnn} % We provide three types of trapping for invalid operations and % division by zero: either produce an error and raise the relevant % flag; or only raise the flag; or don't even raise the flag. In all % cases, the function must produce a result, namely its first % argument, $\pm\infty$ or \nan{}. % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_trap_invalid_operation_set_error: - { \@@_trap_invalid_operation_set:N \prg_do_nothing: } -\cs_new_protected_nopar:Npn \@@_trap_invalid_operation_set_flag: - { \@@_trap_invalid_operation_set:N \use_none:nn } -\cs_new_protected_nopar:Npn \@@_trap_invalid_operation_set_none: - { \@@_trap_invalid_operation_set:N \use_none:nnnn } -\cs_new_protected:Npn \@@_trap_invalid_operation_set:N #1 - { - \@@_trap_invalid_operation_set:Nnn #1 - { invalid_operation } { Invalid~operation~ } - } \cs_new_protected_nopar:Npn \@@_trap_division_by_zero_set_error: { \@@_trap_division_by_zero_set:N \prg_do_nothing: } \cs_new_protected_nopar:Npn \@@_trap_division_by_zero_set_flag: - { \@@_trap_division_by_zero_set:N \use_none:nn } + { \@@_trap_division_by_zero_set:N \use_none:nnnnn } \cs_new_protected_nopar:Npn \@@_trap_division_by_zero_set_none: - { \@@_trap_division_by_zero_set:N \use_none:nnnn } + { \@@_trap_division_by_zero_set:N \use_none:nnnnnnn } \cs_new_protected:Npn \@@_trap_division_by_zero_set:N #1 { - \@@_trap_invalid_operation_set:Nnn #1 - { division_by_zero } { Division~by~zero~in~ } - } -\cs_new_protected:Npn \@@_trap_invalid_operation_set:Nnn #1#2#3 - { \exp_args:Nno \use:n - { \cs_set:cpn { @@_ #2 :Nnw } ##1##2##3; } + { \cs_set:Npn \@@_division_by_zero_o:Nnw ##1##2##3; } { #1 - \@@_error:x { { #3 ##2 } ( \@@_to_tl:w ##3; ) } - \@@_flag_on:n {#2} + \@@_error:nffn { zero-div } {##2} { \@@_to_tl:w ##3; } { } + \fp_flag_on:n { division_by_zero } \exp_after:wN ##1 } \exp_args:Nno \use:n - { \cs_set:cpn { @@_ #2 :Nnww } ##1##2##3; ##4; } + { \cs_set:Npn \@@_division_by_zero_o:NNww ##1##2##3; ##4; } { #1 - \@@_error:x - { - {#3} - \tl_if_single:nTF {##2} - { ( \@@_to_tl:w ##3; ) ##2 ( \@@_to_tl:w ##4; ) } - { { ##2 ( } \@@_to_tl:w ##3; { , ~ } \@@_to_tl:w ##4; ) } - } - \@@_flag_on:n {#2} + \@@_error:nffn { zero-div-ii } + { \@@_to_tl:w ##3; } { \@@_to_tl:w ##4; } {##2} + \fp_flag_on:n { division_by_zero } \exp_after:wN ##1 } } % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} % % \begin{macro}[aux] % { @@ -271,7 +292,7 @@ % \begin{macro}[aux]{\@@_trap_overflow_set:NnNn} % Just as for invalid operations and division by zero, the three % different behaviours are obtained by feeding \cs{prg_do_nothing:}, -% \cs{use_none:nn} or \cs{use_none:nnnn} to an auxiliary, with a +% \cs{use_none:nnnnn} or \cs{use_none:nnnnnnn} to an auxiliary, with a % further auxiliary common to overflow and underflow functions. In % most cases, the argument of the \cs{@@_overflow:w} and % \cs{@@_underflow:w} functions will be an (almost) normal number @@ -286,17 +307,17 @@ \cs_new_protected_nopar:Npn \@@_trap_overflow_set_error: { \@@_trap_overflow_set:N \prg_do_nothing: } \cs_new_protected_nopar:Npn \@@_trap_overflow_set_flag: - { \@@_trap_overflow_set:N \use_none:nn } + { \@@_trap_overflow_set:N \use_none:nnnnn } \cs_new_protected_nopar:Npn \@@_trap_overflow_set_none: - { \@@_trap_overflow_set:N \use_none:nnnn } + { \@@_trap_overflow_set:N \use_none:nnnnnnn } \cs_new_protected:Npn \@@_trap_overflow_set:N #1 { \@@_trap_overflow_set:NnNn #1 { overflow } \@@_inf_fp:N { inf } } \cs_new_protected_nopar:Npn \@@_trap_underflow_set_error: { \@@_trap_underflow_set:N \prg_do_nothing: } \cs_new_protected_nopar:Npn \@@_trap_underflow_set_flag: - { \@@_trap_underflow_set:N \use_none:nn } + { \@@_trap_underflow_set:N \use_none:nnnnn } \cs_new_protected_nopar:Npn \@@_trap_underflow_set_none: - { \@@_trap_underflow_set:N \use_none:nnnn } + { \@@_trap_underflow_set:N \use_none:nnnnnnn } \cs_new_protected:Npn \@@_trap_underflow_set:N #1 { \@@_trap_overflow_set:NnNn #1 { underflow } \@@_zero_fp:N { 0 } } \cs_new_protected:Npn \@@_trap_overflow_set:NnNn #1#2#3#4 @@ -305,16 +326,12 @@ { \cs_set:cpn { @@_ #2 :w } \s_@@ \@@_chk:w ##1##2##3; } { #1 - \@@_error:x - { - \token_if_eq_meaning:NNTF 1 ##1 - { - \@@_to_tl:w \s_@@ \@@_chk:w ##1##2##3; ~ #2 ed ~ to ~ - \token_if_eq_meaning:NNF 0 ##2 { - } #4 . - } - { An~#2~occurred. } - } - \@@_flag_on:n {#2} + \@@_error:nffn + { flow \if_meaning:w 1 ##1 -to \fi: } + { \@@_to_tl:w \s_@@ \@@_chk:w ##1##2##3; } + { \token_if_eq_meaning:NNF 0 ##2 { - } #4 } + {#2} + \fp_flag_on:n {#2} #3 ##2 } } @@ -323,10 +340,11 @@ % \end{macro} % \end{macro} % -% \begin{macro}[int] +% \begin{macro}[int, EXP] % { -% \@@_invalid_operation:Nnw, \@@_invalid_operation:Nnww, -% \@@_division_by_zero:Nnw, \@@_division_by_zero:Nnww, +% \@@_invalid_operation:nnw, \@@_invalid_operation_o:Nww, +% \@@_array_invalid_operation_o:nw, +% \@@_division_by_zero_o:Nnw, \@@_division_by_zero_o:NNww, % \@@_overflow:w , \@@_underflow:w % } % Initialize the two control sequences (to log properly their @@ -334,55 +352,71 @@ % division by zero, overflow, and underflow to act silently on their % flag. % \begin{macrocode} -\cs_new_protected_nopar:Npn \@@_invalid_operation:Nnw { } -\cs_new_protected_nopar:Npn \@@_invalid_operation:Nnww { } -\cs_new_protected_nopar:Npn \@@_division_by_zero:Nnw { } -\cs_new_protected_nopar:Npn \@@_division_by_zero:Nnww { } -\cs_new_protected_nopar:Npn \@@_overflow:w { } -\cs_new_protected_nopar:Npn \@@_underflow:w { } -\@@_trap:nn { invalid_operation } { error } -\@@_trap:nn { division_by_zero } { flag } -\@@_trap:nn { overflow } { flag } -\@@_trap:nn { underflow } { flag } +\cs_new:Npn \@@_invalid_operation:nnw #1#2#3; { } +\cs_new:Npn \@@_invalid_operation_o:Nww #1#2; #3; { } +\cs_new:Npn \@@_array_invalid_operation_o:nw #1 #2 @ { } +\cs_new:Npn \@@_division_by_zero_o:Nnw #1#2#3; { } +\cs_new:Npn \@@_division_by_zero_o:NNww #1#2#3; #4; { } +\cs_new:Npn \@@_overflow:w { } +\cs_new:Npn \@@_underflow:w { } +\fp_trap:nn { invalid_operation } { error } +\fp_trap:nn { division_by_zero } { flag } +\fp_trap:nn { overflow } { flag } +\fp_trap:nn { underflow } { flag } % \end{macrocode} % \end{macro} % -%^^A todo: first arg of @@_invalid_operation:Nnw(w) should be an 'invalid' nan. +% \begin{macro}[int, EXP] +% {\@@_invalid_operation_o:nw} +% Convenient short-hands for returning \cs{c_nan_fp} for a unary or +% binary operation, and expanding after. +% \begin{macrocode} +\cs_new_nopar:Npn \@@_invalid_operation_o:nw + { \@@_invalid_operation:nnw { \exp_after:wN \c_nan_fp } } +% \end{macrocode} +% \end{macro} % % \subsection{Errors} % %^^A begin[todo] -% \begin{macro}[int, EXP]{\@@_error:n, \@@_error:x} -% The argument is fully expanded in a way similar to \texttt{x}-type -% expansion, but braced groups are simply copied, \cs{exp_not:n} does -% not work, spaces are ignored unless braced. The result of that -% weird (but useful) expansion is fed to \cs{__msg_expandable_error:n}. +% \begin{macro}[int, EXP]{\@@_error:nnnn, \@@_error:nffn} +% \begin{macrocode} +\cs_new:Npn \@@_error:nnnn #1 + { \__msg_kernel_expandable_error:nnnnn { kernel } { fp - #1 } } +\cs_generate_variant:Nn \@@_error:nnnn { nff } +% \end{macrocode} +% \end{macro} +% ^^A end[todo] +% +% ^^A todo: move \@@_array_to_clist:w elsewhere. +% \begin{macro}[int, EXP]{\@@_array_to_clist:w} +% \begin{macro}[aux, EXP]{\@@_array_to_clist_i:wwww, \@@_array_to_clist_ii:ww} +% Converts an array of floating point numbers to a comma-list. Does +% not work for empty arrays. % \begin{macrocode} -\cs_new_eq:NN \@@_error:n \__msg_expandable_error:n -\cs_new:Npn \@@_error:x #1 +\cs_new:Npn \@@_array_to_clist:w #1 @ { - \exp_args:Nf \__msg_expandable_error:n - { - \@@_error_loop:nwnN { \exp_stop_f: } #1 \prg_do_nothing: - \s_@@_mark { } \@@_error_loop:nwnN \s_@@_mark { } \@@_error_end:nw - } + \@@_array_to_clist_i:wwww ; + #1 + \@@_array_to_clist_ii:ww \s_@@ ; @ } -\cs_new:Npn \@@_error_end:nw #1#2 \@@_error_end:nw { #1 } -\cs_new:Npn \@@_error_loop:nwnN #1#2 \s_@@_mark #3 #4 +\cs_new:Npn \@@_array_to_clist_i:wwww #1; #2 \s_@@ #3; #4 @ { - \exp_after:wN #4 \tex_romannumeral:D -`0 #2 - \s_@@_mark { #3 #1 } #4 + \exp_after:wN \@@_array_to_clist_i:wwww + \tex_romannumeral:D -`0 \@@_to_tl:w \s_@@ #3 ; ; + #4 , ~ #1 @ } +\cs_new:Npn \@@_array_to_clist_ii:ww #1 ; , ~ , ~ #2 @ {#2} % \end{macrocode} % \end{macro} -% ^^A end[todo] +% \end{macro} % % \subsection{Messages} % % Some messages. % \begin{macrocode} -\msg_new:nnnn { kernel } { unknown-fpu-exception } +\__msg_kernel_new:nnnn { kernel } { unknown-fpu-exception } { The~FPU~exception~'#1'~is~not~known:~that~trap~will~never~be~triggered. } { The~only~exceptions~to~which~traps~can~be~attached~are \\ @@ -394,7 +428,7 @@ * ~ underflow } } -\msg_new:nnnn { kernel } { unknown-fpu-trap-type } +\__msg_kernel_new:nnnn { kernel } { unknown-fpu-trap-type } { The~FPU~trap~type~'#2'~is~not~known. } { The~trap~type~must~be~one~of \\ @@ -405,6 +439,18 @@ * ~ none } } +\__msg_kernel_new:nnn { kernel } { fp-flow } + { An ~ #3 ~ occurred. } +\__msg_kernel_new:nnn { kernel } { fp-flow-to } + { #1 ~ #3 ed ~ to ~ #2 . } +\__msg_kernel_new:nnn { kernel } { fp-zero-div } + { Division~by~zero~in~ #1 (#2) } +\__msg_kernel_new:nnn { kernel } { fp-zero-div-ii } + { Division~by~zero~in~ (#1) #3 (#2) } +\__msg_kernel_new:nnn { kernel } { fp-invalid } + { Invalid~operation~ #1 (#2) } +\__msg_kernel_new:nnn { kernel } { fp-invalid-ii } + { Invalid~operation~ (#1) #3 (#2) } % \end{macrocode} % % \begin{macrocode} @@ -415,4 +461,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx index 16a3fb465f6..d6682a661c3 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx @@ -35,7 +35,7 @@ %% % %<*driver> -\RequirePackage{l3names} +\RequirePackage{l3bootstrap} \GetIdInfo$Id: l3fp-trig.dtx 3514 2012-03-08 06:14:48Z bruno $ {L3 Floating-point trigonometric functions} \documentclass[full]{l3doc} @@ -116,7 +116,7 @@ % % \subsubsection{Sign and special numbers} % -% \begin{macro}[int, EXP]{\@@_sin:w} +% \begin{macro}[int, EXP]{\@@_sin_o:w} % The sine of $\pm 0$ or \nan{} is the same floating point number. % The sine of $\pm\infty$ raises an invalid operation exception. % Otherwise, check the exponent, preparing to use @@ -124,7 +124,7 @@ % an initial octant of $0$. The question mark is an argument which is % not used in this case. % \begin{macrocode} -\cs_new:Npn \@@_sin:w \s_@@ \@@_chk:w #1#2 +\cs_new:Npn \@@_sin_o:w \s_@@ \@@_chk:w #1#2 { \if_case:w #1 \exp_stop_f: \@@_case_return_same_o:w @@ -135,8 +135,7 @@ \exp_after:wN #2 \exp_after:wN \c_zero \or: - \@@_case_use:nw - { \@@_invalid_operation:Nnw \c_nan_fp { sin } } + \@@_case_use:nw { \@@_invalid_operation_o:nw { sin } } \else: \@@_case_return_same_o:w \fi: \s_@@ \@@_chk:w #1#2 @@ -144,7 +143,7 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[int, EXP]{\@@_cos:w} +% \begin{macro}[int, EXP]{\@@_cos_o:w} % The cosine of $\pm 0$ is $1$. The cosine of $\pm\infty$ raises an % invalid operation exception. The cosine of \nan{} is itself. % Otherwise, check the exponent, preparing to use @@ -153,7 +152,7 @@ % + |x|)$. The question mark is an argument which is not used in this % case. % \begin{macrocode} -\cs_new:Npn \@@_cos:w \s_@@ \@@_chk:w #1#2 +\cs_new:Npn \@@_cos_o:w \s_@@ \@@_chk:w #1#2 { \if_case:w #1 \exp_stop_f: \@@_case_return_o:Nw \c_one_fp @@ -167,8 +166,7 @@ \c_two } \or: - \@@_case_use:nw - { \@@_invalid_operation:Nnw \c_nan_fp { cos } } + \@@_case_use:nw { \@@_invalid_operation_o:nw { cos } } \else: \@@_case_return_same_o:w \fi: \s_@@ \@@_chk:w #1#2 @@ -176,16 +174,16 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[int, EXP]{\@@_tan:w} +% \begin{macro}[int, EXP]{\@@_tan_o:w} % The tangent of $\pm 0$ or \nan{} is the same floating point number. % The tangent of $\pm\infty$ raises an invalid operation exception. % Otherwise, check the exponent, preparing to use % \cs{@@_tan_series:NNwww} for the calculation, with a positive sign % ($0$), and an initial octant of $1$, chosen to be distinct from the -% octants for sine and cosine. See \cs{@@_cot:w} for an +% octants for sine and cosine. See \cs{@@_cot_o:w} for an % explanation of the $0$ argument. % \begin{macrocode} -\cs_new:Npn \@@_tan:w \s_@@ \@@_chk:w #1#2 +\cs_new:Npn \@@_tan_o:w \s_@@ \@@_chk:w #1#2 { \if_case:w #1 \exp_stop_f: \@@_case_return_same_o:w @@ -196,8 +194,7 @@ \exp_after:wN #2 \exp_after:wN \c_one \or: - \@@_case_use:nw - { \@@_invalid_operation:Nnw \c_nan_fp { tan } } + \@@_case_use:nw { \@@_invalid_operation_o:nw { tan } } \else: \@@_case_return_same_o:w \fi: \s_@@ \@@_chk:w #1#2 @@ -205,7 +202,7 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[int, EXP]{\@@_cot:w} +% \begin{macro}[int, EXP]{\@@_cot_o:w} % The cotangent of $\pm 0$ is $\pm \infty$ with the same sign, % produced by \cs{@@_one_over:w}. The cotangent of $\pm\infty$ raises % an invalid operation exception. The cotangent of \nan{} is itself. @@ -216,7 +213,7 @@ % indicates whether we compute tangent or cotangent. Those signs are % eventually combined. % \begin{macrocode} -\cs_new:Npn \@@_cot:w \s_@@ \@@_chk:w #1#2 +\cs_new:Npn \@@_cot_o:w \s_@@ \@@_chk:w #1#2 { \if_case:w #1 \exp_stop_f: \exp_after:wN \@@_one_over:w @@ -227,8 +224,7 @@ \exp_after:wN #2 \exp_after:wN \c_three \or: - \@@_case_use:nw - { \@@_invalid_operation:Nnw \c_nan_fp { cot } } + \@@_case_use:nw { \@@_invalid_operation_o:nw { cot } } \else: \@@_case_return_same_o:w \fi: \s_@@ \@@_chk:w #1#2 @@ -578,4 +574,4 @@ % % \PrintChanges % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx index 68f71f540cc..059ca848304 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx @@ -35,8 +35,8 @@ %% % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3fp.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3fp.dtx 4089 2012-08-14 04:52:20Z bruno $ {L3 Floating points} %</driver|package> %<*driver> @@ -71,33 +71,40 @@ % % \begin{documentation} % -% A floating point number is one which is stored as a mantissa and a +% A decimal floating point number is one which is stored as a mantissa and a % separate exponent. The module implements expandably a wide set of -% arithmetic, trigonometric, and other operations on floating point +% arithmetic, trigonometric, and other operations on decimal floating point % numbers, to be used within floating point expressions. Floating point % expressions support the following operations with their usual % precedence. % \begin{itemize} % \item Basic arithmetic: addition $x+y$, subtraction $x-y$, % multiplication $x*y$, division $x/y$, and parentheses. -% \item Trigonometry: $\sin x$, $\cos x$, $\tan x$, $\cot x$. +% \item Comparison operators: $x\mathop{\mathtt{<}}y$, +% $x\mathop{\mathtt{<=}}y$, $x\mathop{\mathtt{>?}}y$, +% $x\mathop{\mathtt{!=}}y$ \emph{etc.} +% \item Boolean logic: negation $\mathop{!}x$, conjunction +% $x\mathop{\&\&}y$, disjunction $x\mathop{\vert\vert}y$, ternary +% operator $x\mathop{?}y\mathop{:}z$. % \item Exponentials: $\exp x$, $\ln x$, $x^y$. -% \item Comparison operators: $x<y$, $x<=y$, $x>?y$, $x!=y$ \emph{etc.} -% \item Boolean logic: negation $!x$, conjunction $\&\&$, disjunction -% $\vert\vert$, ternary operator $x?y:z$. -% \item [\emph{not yet}] Inverse trigonometric functions: +% \item Trigonometry: $\sin x$, $\cos x$, $\tan x$, $\cot x$. +% \emph{Not yet:} $\sec x$, $\csc x$. +% \item [\emph{(not yet)}] Inverse trigonometric functions: % $\operatorname{asin} x$, $\operatorname{acos} x$, -% $\operatorname{atan} x$, $\operatorname{acot} x$. -% \item [\emph{not yet}] Hyperbolic functions and their inverse -% functions: $\sinh x$, $\cosh x$, $\tanh x$, $\coth x$, and +% $\operatorname{atan} x$, $\operatorname{acot} x$, +% $\operatorname{asec} x$, $\operatorname{acsc} x$. +% \item [\emph{(not yet)}] Hyperbolic functions and their inverse +% functions: $\sinh x$, $\cosh x$, $\tanh x$, $\coth x$, +% $\operatorname{sech} x$, $\operatorname{csch}$, and % $\operatorname{asinh} x$, $\operatorname{acosh} x$, -% $\operatorname{atanh} x$, $\operatorname{acoth} x$. +% $\operatorname{atanh} x$, $\operatorname{acoth} x$, +% $\operatorname{asech} x$, $\operatorname{acsch} x$. % \item Extrema: $\max(x,y,\ldots)$, $\min(x,y,\ldots)$, % $\operatorname{abs}(x)$. % \item Rounding functions: $\operatorname{round}(x,n)$ round to -% closest, $\operatorname{round} 0(x,n)$ round towards zero, -% $\operatorname{round}\pm(x,n)$ round towards $\pm\infty$. And -% (\emph{not yet}) modulo, and \enquote{quantize}. +% closest, $\operatorname{round0}(x,n)$ round towards zero, +% $\operatorname{round\pm}(x,n)$ round towards $\pm\infty$. And +% \emph{(not yet)} modulo, and \enquote{quantize}. % \item Constants: \texttt{pi}, \texttt{deg} (one degree in radians). % \item Dimensions, automatically expressed in points, \emph{e.g.}, % \texttt{pc} is $12$. @@ -134,7 +141,8 @@ % % \section{Creating and initialising floating point variables} % -% \begin{function}[updated = 2012-05-08]{\fp_new:N, \fp_new:c} +% \begin{function}[updated = 2012-05-08, tested = m3fp001] +% {\fp_new:N, \fp_new:c} % \begin{syntax} % \cs{fp_new:N} \meta{fp~var} % \end{syntax} @@ -143,7 +151,8 @@ % initially be $+0$. % \end{function} % -% \begin{function}[updated = 2012-05-08]{\fp_const:Nn, \fp_const:cn} +% \begin{function}[updated = 2012-05-08, tested = m3fp001] +% {\fp_const:Nn, \fp_const:cn} % \begin{syntax} % \cs{fp_const:Nn} \meta{fp~var} \Arg{floating point expression} % \end{syntax} @@ -152,7 +161,7 @@ % the result of evaluating the \meta{floating point expression}. % \end{function} % -% \begin{function}[updated = 2012-05-08] +% \begin{function}[updated = 2012-05-08, tested = m3fp001] % {\fp_zero:N, \fp_zero:c, \fp_gzero:N, \fp_gzero:c} % \begin{syntax} % \cs{fp_zero:N} \meta{fp~var} @@ -160,7 +169,7 @@ % Sets the \meta{fp~var} to~$+0$. % \end{function} % -% \begin{function}[updated = 2012-05-08] +% \begin{function}[updated = 2012-05-08, tested = m3fp001] % {\fp_zero_new:N, \fp_zero_new:c, \fp_gzero_new:N, \fp_gzero_new:c} % \begin{syntax} % \cs{fp_zero_new:N} \meta{fp~var} @@ -250,10 +259,11 @@ % Evaluates the \meta{floating point expression} and expresses the % result as a dimension (in \texttt{pt}) suitable for use in dimension % expressions. The output is identical to \cs{fp_to_decimal:n}, with -% an additional trailing \texttt{pt}. In particular, floating point -% numbers outside the range $[- 2^{14} + 2^{-17}, 2^{14} - 2^{-17}]$ -% overflow \TeX{}'s maximum dimension. The values $\pm\infty$ and -% \texttt{nan} trigger an \enquote{invalid operation} exception. +% an additional trailing \texttt{pt}. In particular, the result may +% be outside the range $[- 2^{14} + 2^{-17}, 2^{14} - 2^{-17}]$ of +% valid \TeX{} dimensions, leading to overflow errors if used as a +% dimension. The values $\pm\infty$ and \texttt{nan} trigger an +% \enquote{invalid operation} exception. % \end{function} % % \begin{function}[EXP, updated = 2012-07-08] @@ -293,15 +303,16 @@ % \cs{fp_to_tl:n} \Arg{floating point expression} % \end{syntax} % Evaluates the \meta{floating point expression} and expresses the -% result in (almost) the shortest possible form. Numbers greater or -% equal to $10^{16}$, or less than $10^{-3}$ are expressed in +% result in (almost) the shortest possible form. Numbers in the +% ranges $(0,10^{-3})$ and $[10^{16},\infty)$ are expressed in % scientific notation with trailing zeros trimmed (see % \cs{fp_to_scientific:n}). Numbers in the range $[10^{-3},10^{16})$ % are expressed in a decimal notation without exponent, with trailing % zeros trimmed, and no decimal separator for integer values (see -% \cs{fp_to_decimal:n}. The special values $\pm 0$, $\pm \inf$ and -% \texttt{nan} are rendered as |0|, |-0|, \texttt{inf}, \texttt{-inf}, -% and \texttt{nan} respectively. +% \cs{fp_to_decimal:n}. Negative numbers start with |-|. The +% special values $\pm 0$, $\pm \inf$ and \texttt{nan} are rendered as +% |0|, |-0|, \texttt{inf}, \texttt{-inf}, and \texttt{nan} +% respectively. % \end{function} % % \begin{function}[EXP, updated = 2012-07-08]{\fp_use:N, \fp_use:c} @@ -384,7 +395,8 @@ % The value of $1^{\circ}$ in radians. Multiply an angle given in % degrees by this value to obtain a result in radians, suitable to be % used for trigonometric functions. Within floating point -% expressions, this can be accessed by \texttt{deg}. +% expressions, this can be accessed as \texttt{deg}. Note that +% \texttt{180 deg = pi} exactly. % \end{variable} % % \begin{variable}{\l_tmpa_fp, \l_tmpb_fp} @@ -403,7 +415,9 @@ % % \section{Floating point exceptions} % \label{sec:fp-exceptions} -%^^A todo: redoc +% +% \emph{The functions defined in this section are experimental, and +% their functionality may be altered or removed altogether.} % % \enquote{Exceptions} may occur when performing some floating point % operations, such as \texttt{0 / 0}, or \texttt{10 ** 1e9999}. The @@ -417,39 +431,48 @@ % number. This results in $\pm 0$. % \item \emph{Invalid operation} occurs for operations with no defined % outcome, for instance $0/0$, or $\sin(\infty)$, and almost any -% operation involving a \nan{}. This results in a \nan{}. +% operation involving a \nan{}. This normally results in a \nan{}, +% except for conversion functions whose target type does not have a +% notion of \nan{} (\emph{e.g.}, \cs{fp_to_dim:n}). % \item \emph{Division by zero} occurs when dividing a non-zero number % by $0$, or when evaluating \emph{e.g.}, $\ln(0)$ or $\cot(0)$. This % results in $\pm\infty$. % \item \emph{Inexact} occurs whenever the result of a computation is -% not exact, in other words, almost always. This exception is -% entirely ignored in \LaTeX3. +% not exact, in other words, almost always. At the moment, this +% exception is entirely ignored in \LaTeX3. % \end{itemize} % To each exception is associated a \enquote{flag}, which can be either -% \emph{on} or \emph{off}. By default, when an exception occurs, the -% corresponding flag is turned on. The state of the flag can be tested +% \emph{on} or \emph{off}. By default, the \enquote{invalid operation} +% exception triggers an (expandable) error, and raises the corresponding +% flag. Other exceptions only raise the corresponding flag. The state +% of the flag can be tested % and modified. The behaviour when an exception occurs can be modified % (using \cs{fp_trap:nn}) to either produce an error and turn the flag % on, or only turn the flag on, or do nothing at all. % -% \begin{function}[EXP, pTF, added = 2012-05-28]{\fp_if_flag_on:n} +% \begin{function}[EXP, pTF, added = 2012-08-08, +% tested = m3fp-traps001]{\fp_if_flag_on:n} % \begin{syntax} % \cs{fp_if_flag_on_p:n} \Arg{exception} % \cs{fp_if_flag_on:nTF} \Arg{exception} \Arg{true code} \Arg{false code} % \end{syntax} % Tests if the flag for the \meta{exception} is on, which normally % means the given \meta{exception} has occurred. +% \emph{This function is experimental, and may be altered or removed.} % \end{function} % -% \begin{function}[added = 2012-05-28]{\fp_flag_off:n} +% \begin{function}[added = 2012-08-08, +% tested = m3fp-traps001]{\fp_flag_off:n} % \begin{syntax} % \cs{fp_flag_off:n} \Arg{exception} % \end{syntax} % Locally turns off the flag which indicates whether the % \meta{exception} has occurred. +% \emph{This function is experimental, and may be altered or removed.} % \end{function} % -% \begin{function}[EXP, added = 2012-05-28]{\fp_flag_on:n} +% \begin{function}[EXP, added = 2012-08-08, +% tested = m3fp-traps001]{\fp_flag_on:n} % \begin{syntax} % \cs{fp_flag_on:n} \Arg{exception} % \end{syntax} @@ -457,9 +480,11 @@ % \meta{exception} has occurred. Note that this function is % expandable: it is used internally by \pkg{l3fp} to signal when % exceptions do occur. +% \emph{This function is experimental, and may be altered or removed.} % \end{function} % -% \begin{function}[added = 2012-05-28]{\fp_trap:nn} +% \begin{function}[added = 2012-07-19, updated = 2012-08-08, +% tested = m3fp-traps001]{\fp_trap:nn} % \begin{syntax} % \cs{fp_trap:nn} \Arg{exception} \Arg{trap type} % \end{syntax} @@ -476,9 +501,10 @@ % the \TeX{} run and display some information about the current % operation in the terminal. % \end{itemize} +% \emph{This function is experimental, and may be altered or removed.} % \end{function} % -% \section{Floating point expressions} +% \section{Viewing floating points} % % \begin{function}[added = 2012-05-08, updated = 2012-05-27] % {\fp_show:N, \fp_show:c, \fp_show:n} @@ -490,10 +516,12 @@ % result in the terminal. % \end{function} % +% \section{Floating point expressions} +% % \subsection{Input of floating point numbers} \label{sec:fp-floats} % -%^^A todo: write a grammar -%^^A todo: clarify what has changed compared to the previous l3fp +% ^^A todo: redoc subsection, write a grammar +% ^^A todo: clarify what has changed compared to the previous l3fp % % We support four types of floating point numbers: % \begin{itemize} @@ -505,7 +533,7 @@ % \item \texttt{nan}, is \enquote{not a number}, and can be either quiet % or signalling (\emph{not yet}: this distinction is currently % unsupported); -% \item [\emph{not yet}] subnormal numbers $\pm 0.d_1d_2\ldots{}d_{16} +% \item [\emph{(not yet)}] subnormal numbers $\pm 0.d_1d_2\ldots{}d_{16} % \cdot 10^{-\ExplSyntaxOn\int_use:N \c__fp_max_exponent_int}$ with % $d_1=0$. % \end{itemize} @@ -562,8 +590,6 @@ % \subsection{Precedence of operators} % \label{sec:fp-precedence} % -% ^^A List "juxtaposition" somewhere in the list. -% % We list here all the operations supported in floating point % expressions, in order of decreasing precedence: operations listed % earlier bind more tightly than operations listed below them. @@ -592,9 +618,11 @@ % % We now present the various operations allowed in floating point % expressions. When used as a truth value, a floating point expression -% is \texttt{false} if it is $\pm 0$, and \texttt{false} otherwise. +% is \texttt{false} if it is $\pm 0$, and \texttt{true} otherwise. % -% The exceptions listed below are mostly not implemented yet. ^^A todo: +% The exceptions listed below are mostly not implemented yet. +% ^^A todo: implement all exceptions already listed. +% ^^A todo: add exceptions to '?:', '!<=>?', etc. % % \begin{function}{?:} % \begin{syntax} @@ -621,7 +649,7 @@ % \end{function} % % \begingroup \catcode`\|=12 -% \begin{function}{TWO BARS} ^^A To fix +% \begin{function}{TWO BARS} ^^A todo:fix % \begin{syntax} % \cs{fp_eval:n} \{ \meta{operand_1} \texttt{||} \meta{operand_2} \} % \end{syntax} @@ -696,8 +724,8 @@ % \end{syntax} % Raises \meta{operand_1} to the power \meta{operand_2}. This operation % is right associative, hence \texttt{2 ** 2 ** 3} equals -% $2\sp{2\sp{3}} = 256$. The \enquote{invalid operation} exception -% occurs if \meta{operand_1} is negative or $-0$, \meta{operand_2} is +% $2^{2^{3}} = 256$. The \enquote{invalid operation} exception +% occurs if \meta{operand_1} is negative or $-0$, and \meta{operand_2} is % not an integer, and the result is non-zero. \enquote{Division by % zero} occurs \emph{not yet}. The \enquote{inexact}, % \enquote{underflow} and \enquote{overflow} exceptions occur when @@ -710,7 +738,8 @@ % \cs{fp_eval:n} \{ |abs(| \meta{fpexpr} |)| \} % \end{syntax} % Computes the absolute value of the \meta{fpexpr}. This function -% never raises an exception when \meta{fpexpr} is a number. +% does not raise any exception beyond those raised when computing its +% operand \meta{fpexpr}. % \end{function} % % \begin{function}{exp} @@ -718,7 +747,7 @@ % \cs{fp_eval:n} \{ |exp(| \meta{fpexpr} |)| \} % \end{syntax} % Computes the exponential of the \meta{fpexpr}. The -% \enquote{inexact}, \enquote{underflow} and \enquote{overflow} +% \enquote{underflow} and \enquote{overflow} % exceptions occur when appropriate. % \end{function} % @@ -728,9 +757,9 @@ % \end{syntax} % Computes the natural logarithm of the \meta{fpexpr}. Negative % numbers have no (real) logarithm, hence the \enquote{invalid -% operation} is raised in that case. \enquote{Division by zero} -% occurs when evaluating the logarithm of $\pm 0$. The -% \enquote{inexact}, \enquote{underflow} and \enquote{overflow} +% operation} is raised in that case, including for $\ln(-0)$. +% \enquote{Division by zero} occurs when evaluating $\ln(+0)$. The +% \enquote{underflow} and \enquote{overflow} % exceptions occur when appropriate. % \end{function} % @@ -822,7 +851,10 @@ % \cs{dim_to_fp:n} \Arg{dimexpr} % \end{syntax} % Expands to an internal floating point number equal to the value of -% the \meta{dimexpr} in \texttt{pt}. +% the \meta{dimexpr} in \texttt{pt}. Since dimension expressions are +% evaluated much faster than their floating point equivalent, +% \cs{dim_to_fp:n} can be used to speed up parts of a computation +% where a low precision is acceptable. % \end{function} % % \begin{function}[EXP, added = 2012-05-14, updated = 2012-07-08]{\fp_abs:n} @@ -862,7 +894,10 @@ % \begin{itemize} % \item Decide what exponent range to consider. % \item Change the internal representation of fp, by replacing braced -% groups of $4$ digits by delimited arguments. +% groups of $4$ digits by delimited arguments. Also consider +% changing the fp structure a bit to allow using +% \cs{pdftex_strcmp:D} to compare (not in \LuaTeX{}: it is too +% slow)? % \item Modulo and remainder, and rounding functions |quantize|, % |quantize0|, |quantize+|, |quantize-|, |quantize=|, |round=|. % Should the modulo also be provided as (catcode 12) |%|? @@ -891,26 +926,54 @@ % \item Add an |array(1,2,3)| and |i=complex(0,1)|. % \item Provide an experimental |map| function? Perhaps easier to % implement if it is a single character, |@sin(1,2)|? -% \item Provide \cs{fp_if_nan:nTF}? +% \item Provide \cs{fp_if_nan:nTF}, and an |isnan| function? % \end{itemize} % \pkg{Pgfmath} also provides box-measurements (depth, height, width), but % boxes are not possible expandably. % % Bugs. (Exclamation points mark important bugs.) % \begin{itemize} -% \item[!] \cs{fp_eval:n} |{nan}| mustn't produce an error. -% \item $1-10^{-16}$ should not give $1$. +% \item Logarithms of numbers very close to $1$ are inaccurate. +% \item \texttt{tan} and \texttt{cot} give very slightly wrong results +% for arguments near $10^{-8}$. % \item When rounding towards $-\infty$, |\dim_to_fp:n {0pt}| should % return $-0$, not $+0$. +% \item The result of $(\pm0)+(\pm0)$ should depend on the rounding +% mode. % \item \texttt{0e9999999999} gives a \TeX{} \enquote{number too % large} error. -% \item \texttt{tan} and \texttt{cot} give very slightly wrong results -% for arguments near $10^{-8}$. -% \item[!] Multiplying $0$ with $\infty$ doesn't trigger an invalid -% operation error. % \item Conversion to integers with \cs{fp_to_int:n} does not check % for overflow. % \item Subnormals are not implemented. +% \item |max(-inf)| will lose any information attached to this |-inf|. +% \item The overflow trap receives the wrong argument in +% \pkg{l3fp-expo} (see |exp(1e5678)| in \file{m3fp-traps001}). +% \end{itemize} +% +% Possible optimizations/improvements. +% \begin{itemize} +% \item It would be nice if the \texttt{parse} auxiliaries for each +% operation were set up in the corresponding module, rather than +% centralizing in \pkg{l3fp-parse}. +% \item Some functions should get an |_o| ending to indicate that they +% expand after their result. +% \item More care should be given to distinguish expandable/restricted +% expandable (auxiliary and internal) functions. +% \item The code for the \texttt{ternary} set of functions is ugly. +% \item There are many |~| missing in the doc to avoid bad line-breaks. +% \item The algorithm for computing the logarithm of the significand +% could be made to use a $5$ terms Taylor series instead of $10$ +% terms by taking $c = 2000/(\lfloor 200x\rfloor +1) \in [10,95]$ +% instead of $c\in [1,10]$. Also, it would then be possible to +% simplify the computation of $t$, using methods similar to +% \cs{@@_fixed_div_to_float:ww}. However, we would then have to +% hard-code the logarithms of $44$ small integers instead of $9$. +% \item Improve notations in the explanations of the division +% algorithm (\pkg{l3fp-basics}). +% \item Understand and document \cs{@@_basics_pack_weird_low:NNNNw} +% and \cs{@@_basics_pack_weird_high:NNNNNNNNw} better. Move the +% other \texttt{basics_pack} auxiliaries to \pkg{l3fp-aux} under a +% better name. % \end{itemize} % % \end{documentation} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx index a12b22a45fb..d0f7ab46de7 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3int.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3int.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Integers} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx index 7e3cc783af2..dea8b1923a9 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3keys.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3keys.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Experimental key-value interfaces} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx index 5fbaea8cbd6..5ae55447bf0 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3luatex.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3luatex.dtx 4049 2012-08-03 14:01:40Z bruno $ {L3 Experimental LuaTeX-specific functions} %</driver|package> %<*driver> @@ -76,30 +76,43 @@ % error: use \cs{luatex_if_engine:T} to avoid this. Details of coding % the \LuaTeX{} engine are detailed in the \LuaTeX{} manual. % -% \begin{function}[EXP]{\lua_now:n, \lua_now:x} +% \begin{function}[EXP, updated = 2012-08-02]{\lua_now:n, \lua_now:x} % \begin{syntax} % \cs{lua_now:n} \Arg{token list} % \end{syntax} % The \meta{token list} is first tokenized by \TeX{}, which will include % converting line ends to spaces in the usual \TeX{} manner and which -% respects currently-applicable \TeX\ category codes. The resulting +% respects currently-applicable \TeX{} category codes. The resulting % \meta{\Lua{} input} is passed to the \Lua{} interpreter for processing. % Each \cs{lua_now:n} block is treated by \Lua{} as a separate chunk. % The \Lua{} interpreter will execute the \meta{\Lua{} input} immediately, % and in an expandable manner. +% \end{function} +% +% \begin{function}[EXP, added = 2012-08-02]{\lua_now_x:n, \lua_now_x:x} +% \begin{syntax} +% \cs{lua_now_x:n} \Arg{token list} +% \end{syntax} +% The \meta{token list} is first tokenized and expanded by \TeX{}, which +% will include converting line ends to spaces in the usual \TeX{} manner and +% which respects currently-applicable \TeX{} category codes. The resulting +% \meta{\Lua{} input} is passed to the \Lua{} interpreter for processing. +% Each \cs{lua_now_x:n} block is treated by \Lua{} as a separate chunk. +% The \Lua{} interpreter will execute the \meta{\Lua{} input} immediately, +% and in an expandable manner. % \begin{texnote} -% \cs{lua_now:x} is the \LuaTeX{} primitive \tn{directlua} renamed. +% \cs{lua_now_x:n} is the \LuaTeX{} primitive \tn{directlua} renamed. % \end{texnote} % \end{function} % % \begin{function}{\lua_shipout:n, \lua_shipout:x} % \begin{syntax} -% \cs{lua_shipout:x} \Arg{token list} +% \cs{lua_shipout:n} \Arg{token list} % \end{syntax} % The \meta{token list} is first tokenized by \TeX{}, which will include % converting line ends to spaces in the usual \TeX{} manner and which % respects currently-applicable \TeX{} category codes. The resulting -% \meta{\Lua{} input} is passed to the \Lua\ interpreter when the +% \meta{\Lua{} input} is passed to the \Lua{} interpreter when the % current page is finalised (\emph{i.e.}~at shipout). Each % \cs{lua_shipout:n} block is treated by \Lua{} as a separate chunk. % The \Lua{} interpreter will execute the \meta{\Lua{} input} during the @@ -230,6 +243,7 @@ %</package> % \end{macrocode} % +% \begin{macro}{\lua_now_x:n, \lua_now_x:x} % \begin{macro}{\lua_now:n, \lua_now:x} % \begin{macro}{\lua_shipout_x:n, \lua_shipout_x:x} % \begin{macro}{\lua_shipout:n, \lua_shipout:x} @@ -241,14 +255,14 @@ % \begin{macrocode} \luatex_if_engine:TF { - \cs_new_eq:NN \lua_now:x \luatex_directlua:D + \cs_new_eq:NN \lua_now_x:n \luatex_directlua:D \cs_new_eq:NN \lua_shipout_x:n \luatex_latelua:D } { - \cs_new:Npn \lua_now:x #1 + \cs_new:Npn \lua_now_x:n #1 { \__msg_kernel_expandable_error:nnn - { kernel } { bad-engine } { \lua_now:x } + { kernel } { bad-engine } { \lua_now_x:n } } \cs_new_protected:Npn \lua_shipout_x:n #1 { @@ -256,8 +270,10 @@ { kernel } { bad-engine } { \lua_shipout_x:n } } } +\cs_generate_variant:Nn \lua_now_x:n { x } \cs_new:Npn \lua_now:n #1 - { \lua_now:x { \exp_not:n {#1} } } + { \lua_now_x:n { \exp_not:n {#1} } } +\cs_generate_variant:Nn \lua_now:n { x } \cs_generate_variant:Nn \lua_shipout_x:n { x } \cs_new_protected:Npn \lua_shipout:n #1 { \lua_shipout_x:n { \exp_not:n {#1} } } @@ -266,6 +282,7 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % % \subsection{Category code tables} % @@ -465,9 +482,9 @@ % \end{variable} % \end{variable} % \end{variable} -% +% % \subsection{Messages} -% +% % \begin{macrocode} \__msg_kernel_new:nnnn { kernel } { bad-engine } { LuaTeX~engine~not~in~use!~Ignoring~#1. } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx index a545ab5e126..5d690ced2cf 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3msg.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3msg.dtx 4077 2012-08-10 23:30:52Z bruno $ {L3 Messages} %</driver|package> %<*driver> @@ -257,7 +257,7 @@ % be converted to strings before being added to the message text: the % \texttt{x}-type variants should be used to expand material. % -% \begin{function}[updated = 2012-06-29] +% \begin{function}[updated = 2012-08-11] % { % \msg_fatal:nnnnnn , % \msg_fatal:nnnnn , @@ -277,7 +277,7 @@ % fatal error the \TeX{} run will halt. % \end{function} % -% \begin{function}[updated = 2012-06-29] +% \begin{function}[updated = 2012-08-11] % { % \msg_critical:nnnnnn , % \msg_critical:nnnnn , @@ -304,7 +304,7 @@ % \end{texnote} % \end{function} % -% \begin{function}[updated = 2012-06-29] +% \begin{function}[updated = 2012-08-11] % { % \msg_error:nnnnnn , % \msg_error:nnnnn , @@ -325,7 +325,7 @@ % input, the run will continue. % \end{function} % -% \begin{function}[updated = 2012-06-29] +% \begin{function}[updated = 2012-08-11] % { % \msg_warning:nnnnnn , % \msg_warning:nnnnn , @@ -346,7 +346,7 @@ % will not be interrupted. % \end{function} % -% \begin{function}[updated = 2012-06-29] +% \begin{function}[updated = 2012-08-11] % { % \msg_info:nnnnnn , % \msg_info:nnnnn , @@ -366,7 +366,7 @@ % The information text will be added to the log file. % \end{function} % -% \begin{function}[updated = 2012-07-14] +% \begin{function}[updated = 2012-08-11] % { % \msg_log:nnnnnn , % \msg_log:nnnnn , @@ -387,7 +387,7 @@ % is briefer than \cs{msg_info:nnnnnn}. % \end{function} % -% \begin{function}[updated = 2012-06-29] +% \begin{function}[updated = 2012-08-11] % { % \msg_none:nnnnnn , % \msg_none:nnnnn , @@ -577,7 +577,7 @@ % these will be supplied and expanded at the time the message is used. % \end{function} % -% \begin{function}[updated = 2012-06-29] +% \begin{function}[updated = 2012-08-11] % { % \__msg_kernel_fatal:nnnnnn , % \__msg_kernel_fatal:nnnnn , @@ -597,7 +597,7 @@ % fatal error the \TeX{} run will halt. Cannot be redirected. % \end{function} % -% \begin{function}[updated = 2012-06-29] +% \begin{function}[updated = 2012-08-11] % { % \__msg_kernel_error:nnnnnn , % \__msg_kernel_error:nnnnn , @@ -619,7 +619,7 @@ % the run will continue. Cannot be redirected. % \end{function} % -% \begin{function}[updated = 2012-06-29] +% \begin{function}[updated = 2012-08-11] % { % \__msg_kernel_warning:nnnnnn , % \__msg_kernel_warning:nnnnn , @@ -641,7 +641,7 @@ % interrupted. % \end{function} % -% \begin{function}[updated = 2012-06-29] +% \begin{function}[updated = 2012-08-11] % { % \__msg_kernel_info:nnnnnn , % \__msg_kernel_info:nnnnn , @@ -888,7 +888,7 @@ % \c_msg_fatal_text_tl , % \c_msg_help_text_tl , % \c_msg_no_info_text_tl , -% \c_msg_on_line_tl , +% \c_msg_on_line_text_tl , % \c_msg_return_text_tl , % \c_msg_trouble_text_tl % } @@ -1109,7 +1109,7 @@ } % \end{macrocode} % \end{macro} -% +% % \begin{macro}{\@@_class_new:nn} % \begin{macrocode} \group_begin: @@ -1119,9 +1119,12 @@ \cs_new_protected:cpn { @@_ #1 _code:nnnnnn } ##1##2##3##4##5##6 {#2} \cs_new_protected:cpn { msg_ #1 :nnnnnn } ##1##2##3##4##5##6 { - \@@_use:nnnnnnn {#1} {##1} {##2} - { \tl_to_str:n {##3} } { \tl_to_str:n {##4} } - { \tl_to_str:n {##5} } { \tl_to_str:n {##6} } + \use:x + { + \exp_not:n { \@@_use:nnnnnnn {#1} {##1} {##2} } + { \tl_to_str:n {##3} } { \tl_to_str:n {##4} } + { \tl_to_str:n {##5} } { \tl_to_str:n {##6} } + } } \cs_new_protected:cpx { msg_ #1 :nnnnn } ##1##2##3##4##5 { \exp_not:c { msg_ #1 :nnnnnn } {##1} {##2} {##3} {##4} {##5} { } } @@ -1131,12 +1134,12 @@ { \exp_not:c { msg_ #1 :nnnnnn } {##1} {##2} {##3} { } { } { } } \cs_new_protected:cpx { msg_ #1 :nn } ##1##2 { \exp_not:c { msg_ #1 :nnnnnn } {##1} {##2} { } { } { } { } } - \cs_new_protected:cpn { msg_ #1 :nnxxxx } ##1##2##3##4##5##6 + \cs_new_protected:cpx { msg_ #1 :nnxxxx } ##1##2##3##4##5##6 { \use:x { - \@@_use:nnnnnnn - { \exp_not:n {#1} } { \exp_not:n {##1} } { \exp_not:n {##2} } + \exp_not:N \exp_not:n + { \exp_not:c { msg_ #1 :nnnnnn } {##1} {##2} } {##3} {##4} {##5} {##6} } } @@ -1608,20 +1611,28 @@ % \end{macro} % \end{macro} % -% \begin{macro}[aux]{\@@_kernel_class_new:nn} -% \begin{macro}[aux]{\@@_kernel_class_new_aux:nn} +% \begin{macro}[aux]{\@@_kernel_class_new:nN} +% \begin{macro}[aux]{\@@_kernel_class_new_aux:nN} % All the functions for kernel messages come in variants ranging % from~$0$ to~$4$ arguments. Those with less than~$4$ arguments are % defined in terms of the $4$-argument variant, in a way very similar -% to \cs{msg_class_set:nn}. This auxiliary is destroyed at the end of +% to \cs{@@_class_new:nn}. This auxiliary is destroyed at the end of % the group. % \begin{macrocode} \group_begin: - \cs_set_protected:Npn \@@_kernel_class_new:nn #1 - { \@@_kernel_class_new_aux:nn { kernel_ #1 } } - \cs_set_protected:Npn \@@_kernel_class_new_aux:nn #1#2 + \cs_set_protected:Npn \@@_kernel_class_new:nN #1 + { \@@_kernel_class_new_aux:nN { kernel_ #1 } } + \cs_set_protected:Npn \@@_kernel_class_new_aux:nN #1#2 { - \cs_new_protected:cpn { @@_ #1 :nnnnnn } ##1##2 {#2} + \cs_new_protected:cpn { @@_ #1 :nnnnnn } ##1##2##3##4##5##6 + { + \use:x + { + \exp_not:n { #2 { LaTeX } { ##1 / ##2 } } + { \tl_to_str:n {##3} } { \tl_to_str:n {##4} } + { \tl_to_str:n {##5} } { \tl_to_str:n {##6} } + } + } \cs_new_protected:cpx { @@_ #1 :nnnnn } ##1##2##3##4##5 { \exp_not:c { @@_ #1 :nnnnnn } {##1} {##2} {##3} {##4} {##5} { } } \cs_new_protected:cpx { @@_ #1 :nnnn } ##1##2##3##4 @@ -1634,9 +1645,8 @@ { \use:x { - \exp_not:c { @@_ #1 :nnnnnn } - { \exp_not:N \exp_not:n {##1} } - { \exp_not:N \exp_not:n {##2} } + \exp_not:N \exp_not:n + { \exp_not:c { @@_ #1 :nnnnnn } {##1} {##2} } {##3} {##4} {##5} {##6} } } @@ -1678,13 +1688,11 @@ % already defined by \pkg{l3basics}; we need to undefine them to avoid % errors. % \begin{macrocode} - \@@_kernel_class_new:nn { fatal } - { \@@_fatal_code:nnnnnn { LaTeX } { #1 / #2 } } + \@@_kernel_class_new:nN { fatal } \@@_fatal_code:nnnnnn \cs_undefine:N \@@_kernel_error:nnxx \cs_undefine:N \@@_kernel_error:nnx \cs_undefine:N \@@_kernel_error:nn - \@@_kernel_class_new:nn { error } - { \@@_error_code:nnnnnn { LaTeX } { #1 / #2 } } + \@@_kernel_class_new:nN { error } \@@_error_code:nnnnnn % \end{macrocode} % \end{macro} % @@ -1712,14 +1720,12 @@ % Kernel messages which can be redirected simply use the machinery for % normal messages, with the module name \enquote{\LaTeX{}}. % \begin{macrocode} - \@@_kernel_class_new:nn { warning } - { \msg_warning:nnxxxx { LaTeX } { #1 / #2 } } - \@@_kernel_class_new:nn { info } - { \msg_info:nnxxxx { LaTeX } { #1 / #2 } } + \@@_kernel_class_new:nN { warning } \msg_warning:nnxxxx + \@@_kernel_class_new:nN { info } \msg_info:nnxxxx % \end{macrocode} % \end{macro} % -% End the group to eliminate \cs{@@_kernel_class_new:nn}. +% End the group to eliminate \cs{@@_kernel_class_new:nN}. % \begin{macrocode} \group_end: % \end{macrocode} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx index 6d4fb15351d..0db3e319bb2 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3prg.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3prg.dtx 4061 2012-08-08 15:19:07Z bruno $ {L3 Control structures} %</driver|package> %<*driver> @@ -166,7 +166,7 @@ % % An example can easily clarify matters here: % \begin{verbatim} -% \prg_set_conditional:Nnn \foo_if_bar:NN { p , T , TF } +% \prg_set_conditional:Npnn \foo_if_bar:NN #1#2 { p , T , TF } % { % \if_meaning:w \l_tmpa_tl #1 % \prg_return_true: @@ -1585,15 +1585,8 @@ % % \begin{macro}{\@@_break_point:} % \begin{macro}{\@@_break:, \@@_break:n} -% Very simple analogs of \cs{@@_break_point:Nn} and -% \cs{@@_map_break:Nn}, for use in fast short-term recursions which -% are not mappings, do not need to support nesting, and in which -% nothing has to be done at the end of the loop. -% \begin{macrocode} -\cs_new_eq:NN \@@_break_point: \prg_do_nothing: -\cs_new:Npn \@@_break: #1 \@@_break_point: { } -\cs_new:Npn \@@_break:n #1#2 \@@_break_point: {#1} -% \end{macrocode} +% Also done in \pkg{l3basics} as in format mode these are needed within +% \pkg{l3alloc}. % \end{macro} % \end{macro} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx index e20e2aa5d26..d27c6c48382 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3prop.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3prop.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Property lists} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx index b85b03440df..1abf6fa9693 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3quark.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3quark.dtx 4065 2012-08-08 21:37:44Z bruno $ {L3 Quarks} %</driver|package> %<*driver> @@ -198,7 +198,7 @@ % % This module provides a uniform interface to intercepting and % terminating loops as when one is doing tail recursion. The building -% blocks follow below. +% blocks follow below and an example is shown in Section~\ref{sec:quark-example}. % % \begin{variable}{/q_recursion_tail} % This quark is appended to the data structure in question and @@ -286,6 +286,66 @@ % stream after the end of the recursion. % \end{function} % +% \section{An example of recursion with quarks} +% \label{sec:quark-example} +% +% Quarks are mainly used internally in the \pkg{expl3} code to define +% recursion functions such as \cs{tl_map_inline:nn} and so on. +% Here is a small example to demonstrate how to use quarks in this fashion. +% We shall define a command called |\my_map_dbl:nn| which takes a token list +% and applies an operation to every \emph{pair} of tokens. +% For example, |\my_map_dbl:nn {abcd} {[--#1--#2--]~}| would produce +% \enquote{\ttfamily [--a--b--]~[--c--d--]~}. +% Using quarks to define such functions simplifies their logic and ensures +% robustness in many cases. +% +% \iffalse +% \begin{macrocode} +%<*exampleonly> +% \end{macrocode} +% \fi +% +% Here's the definition of |\my_map_dbl:nn|. +% First of all, define the function that will do the processing based on the +% inline function argument |#2|. +% Then initiate the recursion using an internal function. +% The token list |#1| is terminated using \cs{q_recursion_tail}, with +% delimiters according to the type of recursion (here a pair of +% \cs{q_recursion_tail}), concluding with \cs{q_recursion_stop}. +% These quarks are used to mark the end of the token list being operated upon. +% \begin{macrocode} +\cs_new:Npn \my_map_dbl:nn #1#2 + { + \cs_set:Npn \__my_map_dbl_fn:nn ##1 ##2 {#2} + \__my_map_dbl:nn #1 \q_recursion_tail \q_recursion_tail \q_recursion_stop + } +% \end{macrocode} +% +% The definition of the internal recursion function follows. +% First check if either of the input tokens are the termination quarks. +% Then, if not, apply the inline function to the two arguments. +% \begin{macrocode} +\cs_new:Nn \__my_map_dbl:nn + { + \quark_if_recursion_tail_stop:n {#1} + \quark_if_recursion_tail_stop:n {#2} + \__my_map_dbl_fn:nn {#1} {#2} +% \end{macrocode} +% Finally, recurse: +% \begin{macrocode} + \__my_map_dbl:nn + } +% \end{macrocode} +% Note that contrarily to \LaTeX3 built-in mapping functions, this +% mapping function cannot be nested, since the second map will overwrite +% the definition of |\__my_map_dbl_fn:nn|. +% +% \iffalse +% \begin{macrocode} +%</exampleonly> +% \end{macrocode} +% \fi +% % \section{Internal quark functions} % % \begin{function} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx index d4a3688a068..38491dd1223 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3seq.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3seq.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Sequences and stacks} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx index b83319e74b3..26797004a54 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx @@ -35,8 +35,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3skip.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3skip.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Dimensions and skips} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx index 08d2630523d..c639989d793 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3tl.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3tl.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Token lists} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx index 6b1af27ca33..60feb350c81 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx @@ -34,8 +34,8 @@ %% ----------------------------------------------------------------------- % %<*driver|package> -\RequirePackage{l3names} -\GetIdInfo$Id: l3token.dtx 3986 2012-07-15 19:23:51Z joseph $ +\RequirePackage{l3bootstrap} +\GetIdInfo$Id: l3token.dtx 4069 2012-08-08 23:12:57Z bruno $ {L3 Experimental token manipulation} %</driver|package> %<*driver> @@ -403,7 +403,7 @@ % % \section{Converting tokens} % -% \begin{function}[EXP]{\token_to_meaning:N} +% \begin{function}[EXP]{\token_to_meaning:N, \token_to_meaning:c} % \begin{syntax} % \cs{token_to_meaning:N} \meta{token} % \end{syntax} @@ -1145,6 +1145,13 @@ % % \subsection{Generic tokens} % +% \begin{macro}{\token_to_meaning:N, \token_to_meaning:c} +% \begin{macro}{\token_to_str:N, \token_to_str:c} +% These are all defined in \pkg{l3basics}, as they are needed +% \enquote{early}. This is just a reminder that that is the case! +% \end{macro} +% \end{macro} +% % \begin{macro}{\token_new:Nn} % Creates a new token. % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx b/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx index 564a45a7ce5..8b479be2279 100644 --- a/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx +++ b/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx @@ -37,8 +37,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2012/07/16] -%<package>\@ifpackagelater{expl3}{2012/07/16} +\RequirePackage{expl3}[2012/08/14] +%<package>\@ifpackagelater{expl3}{2012/08/14} %<package> {} %<package> {% %<package> \PackageError{l3keys2e}{Support package l3kernel too old.} @@ -50,7 +50,7 @@ %<package> \endinput %<package> } \RequirePackage{xparse} -\GetIdInfo$Id: l3keys2e.dtx 3990 2012-07-16 07:46:03Z joseph $ +\GetIdInfo$Id: l3keys2e.dtx 4091 2012-08-14 08:13:50Z joseph $ {LaTeX2e option processing using LaTeX3 keys} %</driver|package> %<*driver> diff --git a/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx b/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx index 1ee8b2a7088..7a867b71117 100644 --- a/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx +++ b/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx @@ -37,7 +37,7 @@ % %<*driver|package> \RequirePackage{amstext,graphicx,l3keys2e,textcomp,xparse,xtemplate} -\GetIdInfo$Id: xfrac.dtx 3875 2012-06-30 12:38:05Z joseph $ +\GetIdInfo$Id: xfrac.dtx 3991 2012-07-16 19:00:35Z joseph $ {L3 Experimental split-level fractions} %</driver|package> %<*driver> @@ -1139,4 +1139,4 @@ % % \end{implementation} % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx index b003f5d012c..8f77a0b3231 100644 --- a/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx +++ b/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx @@ -41,8 +41,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2012/07/16] -%<package>\@ifpackagelater{expl3}{2012/07/16} +\RequirePackage{expl3}[2012/08/14] +%<package>\@ifpackagelater{expl3}{2012/08/14} %<package> {} %<package> {% %<package> \PackageError{xparse}{Support package l3kernel too old.} @@ -53,7 +53,7 @@ %<package> }% %<package> \endinput %<package> } -\GetIdInfo$Id: xparse.dtx 3990 2012-07-16 07:46:03Z joseph $ +\GetIdInfo$Id: xparse.dtx 4091 2012-08-14 08:13:50Z joseph $ {L3 Experimental document command parser} %</driver|package> %<*driver> @@ -1063,36 +1063,18 @@ { \@@_declare_cmd_internal:cnx { environment~ #1 } {#2} { - \group_begin: - \cs_set_protected_nopar:Npx \exp_not:c { environment_ #1 _end_aux: } - { - \exp_not:c { environment_ #1 _end_aux:w } - \exp_not:n - { - \exp_args:No \exp_not:o - { \exp_after:wN \use_none:n \l_@@_args_tl } -%<*initex> - \group_end: -%</initex> -%<*package> - \exp_not:n - { - \if@endpe - \exp_after:wN \group_end: - \exp_after:wN \@endpetrue - \else - \exp_after:wN \group_end: - \fi - } -%</package> - } - } + \cs_set_protected_nopar:Npx \exp_not:c { environment~ #1 ~end~aux } + { + \exp_not:c { environment~ #1~end~aux~ } + \exp_not:n + { { \tl_tail:N \l_@@_args_tl } } + } \exp_not:n {#3} } \cs_set_protected_nopar:cpx { environment~ #1 ~end } - { \exp_not:c { environment_ #1 _end_aux: } } + { \exp_not:c { environment~ #1 ~end~aux } } \cs_generate_from_arg_count:cNnn - { environment_ #1 _end_aux:w } \cs_set_protected:Npn + { environment~ #1 ~end~aux~ } \cs_set_protected:Npn \l_@@_current_arg_int {#4} %<*package> \cs_set_eq:cc {#1} { environment~ #1 } @@ -3442,4 +3424,4 @@ % % \end{implementation} % -% \PrintIndex
\ No newline at end of file +% \PrintIndex diff --git a/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx b/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx index 790c5667742..efe49ab6781 100644 --- a/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx +++ b/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx @@ -41,8 +41,8 @@ %<*driver|package> % The version of expl3 required is tested as early as possible, as % some really old versions do not define \ProvidesExplPackage. -\RequirePackage{expl3}[2012/07/16] -%<package>\@ifpackagelater{expl3}{2012/07/16} +\RequirePackage{expl3}[2012/08/14] +%<package>\@ifpackagelater{expl3}{2012/08/14} %<package> {} %<package> {% %<package> \PackageError{xtemplate}{Support package l3kernel too old.} @@ -53,7 +53,7 @@ %<package> }% %<package> \endinput %<package> } -\GetIdInfo$Id: xtemplate.dtx 3990 2012-07-16 07:46:03Z joseph $ +\GetIdInfo$Id: xtemplate.dtx 4091 2012-08-14 08:13:50Z joseph $ {L3 Experimental prototype document functions} %</driver|package> %<*driver> |