diff options
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3fp-logic.dtx')
-rw-r--r-- | macros/latex/contrib/l3kernel/l3fp-logic.dtx | 750 |
1 files changed, 0 insertions, 750 deletions
diff --git a/macros/latex/contrib/l3kernel/l3fp-logic.dtx b/macros/latex/contrib/l3kernel/l3fp-logic.dtx deleted file mode 100644 index c95704085c..0000000000 --- a/macros/latex/contrib/l3kernel/l3fp-logic.dtx +++ /dev/null @@ -1,750 +0,0 @@ -% \iffalse meta-comment -% -%% File: l3fp-logic.dtx -% -% Copyright (C) 2011-2024 The LaTeX Project -% -% It may be distributed and/or modified under the conditions of the -% LaTeX Project Public License (LPPL), either version 1.3c of this -% license or (at your option) any later version. The latest version -% of this license is in the file -% -% https://www.latex-project.org/lppl.txt -% -% This file is part of the "l3kernel bundle" (The Work in LPPL) -% and all files in that bundle must be distributed together. -% -% ----------------------------------------------------------------------- -% -% The development version of the bundle can be found at -% -% https://github.com/latex3/latex3 -% -% for those people who are interested. -% -%<*driver> -\documentclass[full,kernel]{l3doc} -\begin{document} - \DocInput{\jobname.dtx} -\end{document} -%</driver> -% \fi -% -% \title{^^A -% The \pkg{l3fp-logic} module\\ -% Floating point conditionals^^A -% } -% \author{^^A -% The \LaTeX{} Project\thanks -% {^^A -% E-mail: -% \href{mailto:latex-team@latex-project.org} -% {latex-team@latex-project.org}^^A -% }^^A -% } -% \date{Released 2024-03-14} -% -% \maketitle -% -% \begin{documentation} -% -% \end{documentation} -% -% \begin{implementation} -% -% \section{\pkg{l3fp-logic} implementation} -% -% \begin{macrocode} -%<*package> -% \end{macrocode} -% -% \begin{macrocode} -%<@@=fp> -% \end{macrocode} -% -% \begin{macro}[EXP]{\@@_parse_word_max:N , \@@_parse_word_min:N} -% Those functions may receive a variable number of arguments. -% \begin{macrocode} -\cs_new:Npn \@@_parse_word_max:N - { \@@_parse_function:NNN \@@_minmax_o:Nw 2 } -\cs_new:Npn \@@_parse_word_min:N - { \@@_parse_function:NNN \@@_minmax_o:Nw 0 } -% \end{macrocode} -% \end{macro} -% -% \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{@@_minmax_o:Nw} \meta{sign} \meta{floating point array} -% \item \cs{@@_not_o:w} |?| \meta{floating point array} (with one floating point number only) -% \item \cs{@@_&_o:ww} \meta{floating point} \meta{floating point} -% \item \cs{@@_|_o:ww} \meta{floating point} \meta{floating point} -% \item \cs{@@_ternary:NwwN}, \cs{@@_ternary_auxi:NwwN}, -% \cs{@@_ternary_auxii:NwwN} have to be understood. -% \end{itemize} -% -% \subsection{Tests} -% -% \begin{macro}[pTF]{\fp_if_exist:N, \fp_if_exist:c} -% Copies of the \texttt{cs} functions defined in \pkg{l3basics}. -% \begin{macrocode} -\prg_new_eq_conditional:NNn \fp_if_exist:N \cs_if_exist:N { TF , T , F , p } -\prg_new_eq_conditional:NNn \fp_if_exist:c \cs_if_exist:c { TF , T , F , p } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[pTF]{\fp_if_nan:n} -% Evaluate and check if the result is a floating point of the same -% kind as \nan{}. -% \begin{macrocode} -\prg_new_conditional:Npnn \fp_if_nan:n #1 { TF , T , F , p } - { - \if:w 3 \exp_last_unbraced:Nf \@@_kind:w { \@@_parse:n {#1} } - \prg_return_true: - \else: - \prg_return_false: - \fi: - } -% \end{macrocode} -% \end{macro} -% -% \subsection{Comparison} -% -% \begin{macro}[pTF, EXP]{\fp_compare:n} -% \begin{macro}[EXP]{\@@_compare_return:w} -% Within floating point expressions, comparison operators are treated -% as operations, so we evaluate |#1|, then compare with $\pm 0$. -% Tuples are \texttt{true}. -% \begin{macrocode} -\prg_new_conditional:Npnn \fp_compare:n #1 { p , T , F , TF } - { - \exp_after:wN \@@_compare_return:w - \exp:w \exp_end_continue_f:w \@@_parse:n {#1} - } -\cs_new:Npn \@@_compare_return:w #1#2#3; - { - \if_charcode:w 0 - \@@_if_type_fp:NTwFw - #1 { \@@_use_i_delimit_by_s_stop:nw #3 \s_@@_stop } - \s_@@ 1 \s_@@_stop - \prg_return_false: - \else: - \prg_return_true: - \fi: - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[pTF, EXP]{\fp_compare:nNn} -% \begin{macro}[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_any: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 - \exp:w \exp_end_continue_f:w \@@_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_any:ww - \exp:w \exp_end_continue_f:w \@@_parse:n {#2} #1; - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_compare_back:ww, \@@_bcmp:ww, \@@_compare_back_any:ww, \@@_compare_nan:w} -% \begin{quote} -% \cs{@@_compare_back_any: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$). 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_back:ww #1#2; #3#4; - { - \cs:w - @@ - \@@_type_from_scan:N #1 - _bcmp - \@@_type_from_scan:N #3 - :ww - \cs_end: - #1#2; #3#4; - } -\cs_new:Npn \@@_compare_back_any:ww #1#2; #3 - { - \@@_if_type_fp:NTwFw - #1 { \@@_if_type_fp:NTwFw #3 \use_i:nn \s_@@ \use_ii:nn \s_@@_stop } - \s_@@ \use_ii:nn \s_@@_stop - \@@_compare_back:ww - { - \cs:w - @@ - \@@_type_from_scan:N #1 - _compare_back - \@@_type_from_scan:N #3 - :ww - \cs_end: - } - #1#2 ; #3 - } -\cs_new:Npn \@@_bcmp: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 #5 - \fi: - \if_meaning:w #2 #5 - \if_meaning:w #1 #4 - \if_meaning:w 1 #1 - \@@_compare_npos:nwnw #6; #3; - \else: - 0 - \fi: - \else: - \if_int_compare:w #4 < #1 - \fi: 1 - \fi: - \else: - \if_int_compare:w #1#4 = \c_zero_int - 0 - \else: - 1 - \fi: - \fi: - \exp_stop_f: - } -\cs_new:Npn \@@_compare_nan:w #1 \fi: \exp_stop_f: { 2 \exp_stop_f: } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_compare_back_tuple:ww, \@@_tuple_compare_back:ww, \@@_tuple_compare_back_tuple:ww} -% \begin{macro}[EXP]{\@@_tuple_compare_back_loop:w} -% Tuple and floating point numbers are not comparable so return $2$ in -% mixed cases or when tuples have a different number of items. -% Otherwise compare pairs of items with \cs{@@_compare_back_any:ww} -% and if any don't match return~$2$ (as \cs{int_value:w} |02| -% \cs{exp_stop_f:}). -% \begin{macrocode} -\cs_new:Npn \@@_compare_back_tuple:ww #1; #2; { 2 } -\cs_new:Npn \@@_tuple_compare_back:ww #1; #2; { 2 } -\cs_new:Npn \@@_tuple_compare_back_tuple:ww - \s_@@_tuple \@@_tuple_chk:w #1; - \s_@@_tuple \@@_tuple_chk:w #2; - { - \int_compare:nNnTF { \@@_array_count:n {#1} } = - { \@@_array_count:n {#2} } - { - \int_value:w 0 - \@@_tuple_compare_back_loop:w - #1 { \s_@@ \prg_break: } ; @ - #2 { \s_@@ \prg_break: } ; - \prg_break_point: - \exp_stop_f: - } - { 2 } - } -\cs_new:Npn \@@_tuple_compare_back_loop:w #1#2 ; #3 @ #4#5 ; - { - \use_none:n #1 - \use_none:n #4 - \if_int_compare:w - \@@_compare_back_any:ww #1 #2 ; #4 #5 ; = \c_zero_int - \else: - 2 \exp_after:wN \prg_break: - \fi: - \@@_tuple_compare_back_loop:w #3 @ - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_compare_npos:nwnw} -% \begin{macro}[EXP]{\@@_compare_significand: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 significands. 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_significand:nnnnnnnn #2 #4 - \else: - \if_int_compare:w #1 < #3 - \fi: 1 - \fi: - } -\cs_new:Npn \@@_compare_significand:nnnnnnnn #1#2#3#4#5#6#7#8 - { - \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 #3#4 < #7#8 - \fi: 1 - \fi: - \else: - \if_int_compare:w #1#2 < #5#6 - \fi: 1 - \fi: - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsection{Floating point expression loops} -% -% \begin{macro}[rEXP] -% { -% \fp_do_until:nn, \fp_do_while:nn, -% \fp_until_do:nn, \fp_while_do:nn -% } -% These are quite easy given the above functions. The |do_until| and -% |do_while| versions execute the body, then test. The |until_do| and -% |while_do| do it the other way round. -% \begin{macrocode} -\cs_new:Npn \fp_do_until:nn #1#2 - { - #2 - \fp_compare:nF {#1} - { \fp_do_until:nn {#1} {#2} } - } -\cs_new:Npn \fp_do_while:nn #1#2 - { - #2 - \fp_compare:nT {#1} - { \fp_do_while:nn {#1} {#2} } - } -\cs_new:Npn \fp_until_do:nn #1#2 - { - \fp_compare:nF {#1} - { - #2 - \fp_until_do:nn {#1} {#2} - } - } -\cs_new:Npn \fp_while_do:nn #1#2 - { - \fp_compare:nT {#1} - { - #2 - \fp_while_do:nn {#1} {#2} - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[rEXP] -% { -% \fp_do_until:nNnn, \fp_do_while:nNnn, -% \fp_until_do:nNnn, \fp_while_do:nNnn -% } -% As above but not using the |nNn| syntax. -% \begin{macrocode} -\cs_new:Npn \fp_do_until:nNnn #1#2#3#4 - { - #4 - \fp_compare:nNnF {#1} #2 {#3} - { \fp_do_until:nNnn {#1} #2 {#3} {#4} } - } -\cs_new:Npn \fp_do_while:nNnn #1#2#3#4 - { - #4 - \fp_compare:nNnT {#1} #2 {#3} - { \fp_do_while:nNnn {#1} #2 {#3} {#4} } - } -\cs_new:Npn \fp_until_do:nNnn #1#2#3#4 - { - \fp_compare:nNnF {#1} #2 {#3} - { - #4 - \fp_until_do:nNnn {#1} #2 {#3} {#4} - } - } -\cs_new:Npn \fp_while_do:nNnn #1#2#3#4 - { - \fp_compare:nNnT {#1} #2 {#3} - { - #4 - \fp_while_do:nNnn {#1} #2 {#3} {#4} - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\fp_step_function:nnnN, \fp_step_function:nnnc} -% \begin{macro}[EXP]{\@@_step:wwwN, \@@_step_fp:wwwN} -% \begin{macro}[EXP]{\@@_step:NnnnnN, \@@_step:NfnnnN} -% The approach here is somewhat similar to -% \cs{int_step_function:nnnN}. There are two subtleties: we use the -% internal parser \cs{@@_parse:n} to avoid converting back and forth -% from the internal representation; and (due to rounding) even a -% non-zero step does not guarantee that the loop counter increases. -% \begin{macrocode} -\cs_new:Npn \fp_step_function:nnnN #1#2#3 - { - \exp_after:wN \@@_step:wwwN - \exp:w \exp_end_continue_f:w \@@_parse_o:n {#1} - \exp:w \exp_end_continue_f:w \@@_parse_o:n {#2} - \exp:w \exp_end_continue_f:w \@@_parse:n {#3} - } -\cs_generate_variant:Nn \fp_step_function:nnnN { nnnc } -% \end{macrocode} -% Only floating point numbers (not tuples) are allowed arguments. -% Only \enquote{normal} floating points (not $\pm 0$, -% $\pm\texttt{inf}$, \texttt{nan}) can be used as step; if positive, -% call \cs{@@_step:NnnnnN} with argument |>| otherwise~|<|. This -% function has one more argument than its integer counterpart, namely -% the previous value, to catch the case where the loop has made no -% progress. Conversion to decimal is done just before calling the -% user's function. -% \begin{macrocode} -\cs_new:Npn \@@_step:wwwN #1#2; #3#4; #5#6; #7 - { - \@@_if_type_fp:NTwFw #1 { } \s_@@ \prg_break: \s_@@_stop - \@@_if_type_fp:NTwFw #3 { } \s_@@ \prg_break: \s_@@_stop - \@@_if_type_fp:NTwFw #5 { } \s_@@ \prg_break: \s_@@_stop - \use_i:nnnn { \@@_step_fp:wwwN #1#2; #3#4; #5#6; #7 } - \prg_break_point: - \use:n - { - \@@_error:nfff { step-tuple } { \fp_to_tl:n { #1#2 ; } } - { \fp_to_tl:n { #3#4 ; } } { \fp_to_tl:n { #5#6 ; } } - } - } -\cs_new:Npn \@@_step_fp:wwwN #1 ; \s_@@ \@@_chk:w #2#3#4 ; #5; #6 - { - \token_if_eq_meaning:NNTF #2 1 - { - \token_if_eq_meaning:NNTF #3 0 - { \@@_step:NnnnnN > } - { \@@_step:NnnnnN < } - } - { - \token_if_eq_meaning:NNTF #2 0 - { - \msg_expandable_error:nnn { kernel } - { zero-step } {#6} - } - { - \@@_error:nnfn { bad-step } { } - { \fp_to_tl:n { \s_@@ \@@_chk:w #2#3#4 ; } } {#6} - } - \use_none:nnnnn - } - { #1 ; } { \c_nan_fp } { \s_@@ \@@_chk:w #2#3#4 ; } { #5 ; } #6 - } -\cs_new:Npn \@@_step:NnnnnN #1#2#3#4#5#6 - { - \fp_compare:nNnTF {#2} = {#3} - { - \@@_error:nffn { tiny-step } - { \fp_to_tl:n {#3} } { \fp_to_tl:n {#4} } {#6} - } - { - \fp_compare:nNnF {#2} #1 {#5} - { - \exp_args:Nf #6 { \@@_to_decimal_dispatch:w #2 } - \@@_step:NfnnnN - #1 { \@@_parse:n { #2 + #4 } } {#2} {#4} {#5} #6 - } - } - } -\cs_generate_variant:Nn \@@_step:NnnnnN { Nf } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\fp_step_inline:nnnn, \fp_step_variable:nnnNn} -% \begin{macro}{\@@_step:NNnnnn} -% As for \cs{int_step_inline:nnnn}, create a global function and apply it, -% following up with a break point. -% \begin{macrocode} -\cs_new_protected:Npn \fp_step_inline:nnnn - { - \int_gincr:N \g__kernel_prg_map_int - \exp_args:NNc \@@_step:NNnnnn - \cs_gset_protected:Npn - { @@_map_ \int_use:N \g__kernel_prg_map_int :w } - } -\cs_new_protected:Npn \fp_step_variable:nnnNn #1#2#3#4#5 - { - \int_gincr:N \g__kernel_prg_map_int - \exp_args:NNc \@@_step:NNnnnn - \cs_gset_protected:Npe - { @@_map_ \int_use:N \g__kernel_prg_map_int :w } - {#1} {#2} {#3} - { - \tl_set:Nn \exp_not:N #4 {##1} - \exp_not:n {#5} - } - } -\cs_new_protected:Npn \@@_step:NNnnnn #1#2#3#4#5#6 - { - #1 #2 ##1 {#6} - \fp_step_function:nnnN {#3} {#4} {#5} #2 - \prg_break_point:Nn \scan_stop: { \int_gdecr:N \g__kernel_prg_map_int } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macrocode} -\msg_new:nnn { fp } { step-tuple } - { Tuple~argument~in~fp_step_...~{#1}{#2}{#3}. } -\msg_new:nnn { fp } { bad-step } - { Invalid~step~size~#2~for~function~#3. } -\msg_new:nnn { fp } { tiny-step } - { Tiny~step~size~(#1+#2=#1)~for~function~#3. } -% \end{macrocode} -% -% \subsection{Extrema} -% -% \begin{macro}[EXP]{\@@_minmax_o:Nw, \@@_minmax_aux_o:Nw} -% First check all operands are floating point numbers. -% The argument~|#1| is $2$~to find the maximum of an array~|#2| of -% floating point numbers, and $0$~to find the minimum. We read -% numbers sequentially, keeping track of the largest (smallest) number -% found so far. If numbers are equal (for instance~$\pm0$), the first -% is kept. We append $-\infty$ ($\infty$), for the case of an empty -% array. Since no number is smaller (larger) than that, this -% additional item only affects the maximum (minimum) in the case of -% |max()| and |min()| with no argument. The weird -% fp-like trailing marker breaks the loop correctly: see the precise -% definition of \cs{@@_minmax_loop:Nww}. -% \begin{macrocode} -\cs_new:Npn \@@_minmax_o:Nw #1 - { - \@@_parse_function_all_fp_o:fnw - { \token_if_eq_meaning:NNTF 0 #1 { min } { max } } - { \@@_minmax_aux_o:Nw #1 } - } -\cs_new:Npn \@@_minmax_aux_o:Nw #1#2 @ - { - \if_meaning:w 0 #1 - \exp_after:wN \@@_minmax_loop:Nww \exp_after:wN + - \else: - \exp_after:wN \@@_minmax_loop:Nww \exp_after:wN - - \fi: - #2 - \s_@@ \@@_chk:w 2 #1 \s_@@_exact ; - \s_@@ \@@_chk:w { 3 \@@_minmax_break_o:w } ; - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_minmax_loop:Nww} -% The first argument is $-$ or $+$ 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} -\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_auxi:ww - \else: - \@@_minmax_auxii:ww - \fi: - \else: - \if_int_compare:w - \@@_compare_back:ww - \s_@@ \@@_chk:w #4#5; - \s_@@ \@@_chk:w #2#3; - = #1 1 \exp_stop_f: - \@@_minmax_auxii:ww - \else: - \@@_minmax_auxi:ww - \fi: - \fi: - \@@_minmax_loop:Nww #1 - \s_@@ \@@_chk:w #2#3; - \s_@@ \@@_chk:w #4#5; - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_minmax_auxi:ww, \@@_minmax_auxii:ww} -% Keep the first/second number, and remove the other. -% \begin{macrocode} -\cs_new:Npn \@@_minmax_auxi:ww #1 \fi: \fi: #2 \s_@@ #3 ; \s_@@ #4; - { \fi: \fi: #2 \s_@@ #3 ; } -\cs_new:Npn \@@_minmax_auxii:ww #1 \fi: \fi: #2 \s_@@ #3 ; - { \fi: \fi: #2 } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[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}[EXP]{\@@_not_o:w, \@@_tuple_not_o:w} -% Return \texttt{true} or \texttt{false}, with two expansions, one to -% exit the conditional, and one to please \pkg{l3fp-parse}. The first -% argument is provided by \pkg{l3fp-parse} and is ignored. -% \begin{macrocode} -\cs_new:Npn \@@_not_o:w #1 \s_@@ \@@_chk:w #2#3; @ - { - \if_meaning:w 0 #2 - \exp_after:wN \exp_after:wN \exp_after:wN \c_one_fp - \else: - \exp_after:wN \exp_after:wN \exp_after:wN \c_zero_fp - \fi: - } -\cs_new:Npn \@@_tuple_not_o:w #1 @ { \exp_after:wN \c_zero_fp } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_&_o:ww, \@@_tuple_&_o:ww, \@@_&_tuple_o:ww, \@@_tuple_&_tuple_o:ww} -% \begin{macro}[EXP]{\@@_|_o:ww, \@@_tuple_|_o:ww, \@@_|_tuple_o:ww, \@@_tuple_|_tuple_o:ww} -% \begin{macro}[EXP]{\@@_and_return:wNw} -% For \texttt{and}, if the first number is zero, return it (with the -% same sign). Otherwise, return the second one. For \texttt{or}, the -% logic is reversed: if the first number is non-zero, return it, -% otherwise return the second number: we achieve that by hi-jacking -% \cs{@@_&_o:ww}, inserting an extra argument, \cs{else:}, before -% \cs{s_@@}. In all cases, expand after the floating point number. -% \begin{macrocode} -\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:Npn \@@_&_tuple_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_tuple_o:w - } - \cs_new:Npn \@@_tuple_&_o:ww #1; { \@@_exp_after_o:w } - \cs_new:Npn \@@_tuple_&_tuple_o:ww #1; { \@@_exp_after_tuple_o:w } - \cs_new:Npn \@@_|_o:ww { \@@_&_o:ww \else: } - \cs_new:Npn \@@_|_tuple_o:ww { \@@_&_tuple_o:ww \else: } - \cs_new:Npn \@@_tuple_|_o:ww #1; #2; { \@@_exp_after_tuple_o:w #1; } - \cs_new:Npn \@@_tuple_|_tuple_o:ww #1; #2; - { \@@_exp_after_tuple_o:w #1; } -\group_end: -\cs_new:Npn \@@_and_return:wNw #1; \fi: #2; - { \fi: \@@_exp_after_o:w #1; } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \subsection{Ternary operator} -% -% \begin{macro}[EXP] -% {\@@_ternary:NwwN, \@@_ternary_auxi:NwwN, \@@_ternary_auxii:NwwN} -% The first function receives the test and the true branch of the |?:| -% ternary operator. It calls \cs{@@_ternary_auxii:NwwN} if the test -% branch is a floating point number $\pm 0$, and otherwise calls -% \cs{@@_ternary_auxi:NwwN}. These functions select one of their two -% arguments. -% \begin{macrocode} -\cs_new:Npn \@@_ternary:NwwN #1 #2#3@ #4@ #5 - { - \if_meaning:w \@@_parse_infix_::N #5 - \if_charcode:w 0 - \@@_if_type_fp:NTwFw - #2 { \use_i:nn \@@_use_i_delimit_by_s_stop:nw #3 \s_@@_stop } - \s_@@ 1 \s_@@_stop - \exp_after:wN \exp_after:wN \exp_after:wN \@@_ternary_auxii:NwwN - \else: - \exp_after:wN \exp_after:wN \exp_after:wN \@@_ternary_auxi:NwwN - \fi: - \exp_after:wN #1 - \exp:w \exp_end_continue_f:w - \@@_exp_after_array_f:w #4 \s_@@_expr_stop - \exp_after:wN @ - \exp:w - \@@_parse_operand:Nw \c_@@_prec_colon_int - \@@_parse_expand:w - \else: - \msg_expandable_error:nnnn - { fp } { missing } { : } { ~for~?: } - \exp_after:wN \@@_parse_continue:NwN - \exp_after:wN #1 - \exp:w \exp_end_continue_f:w - \@@_exp_after_array_f:w #4 \s_@@_expr_stop - \exp_after:wN #5 - \exp_after:wN #1 - \fi: - } -\cs_new:Npn \@@_ternary_auxi:NwwN #1#2@#3@#4 - { - \exp_after:wN \@@_parse_continue:NwN - \exp_after:wN #1 - \exp:w \exp_end_continue_f:w - \@@_exp_after_array_f:w #2 \s_@@_expr_stop - #4 #1 - } -\cs_new:Npn \@@_ternary_auxii:NwwN #1#2@#3@#4 - { - \exp_after:wN \@@_parse_continue:NwN - \exp_after:wN #1 - \exp:w \exp_end_continue_f:w - \@@_exp_after_array_f:w #3 \s_@@_expr_stop - #4 #1 - } -% \end{macrocode} -% \end{macro} -% -% \begin{macrocode} -%</package> -% \end{macrocode} -% -% \end{implementation} -% -% \PrintChanges -% -% \PrintIndex |