summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx174
1 files changed, 123 insertions, 51 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
index 678c76cdf7c..77a092f8f00 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
@@ -38,7 +38,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2018/02/21}
+% \date{Released 2018/03/05}
%
% \maketitle
%
@@ -96,16 +96,20 @@
% \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 $0$.
+% 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 \s_@@ \@@_chk:w #1#2;
+\cs_new:Npn \@@_compare_return:w #1#2#3;
{
- \if_meaning:w 0 #1
+ \if_charcode:w 0
+ \@@_if_type_fp:NTwFw
+ #1 { \use_i_delimit_by_q_stop:nw #3 \q_stop }
+ \s_@@ 1 \q_stop
\prg_return_false:
\else:
\prg_return_true:
@@ -118,7 +122,7 @@
% \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:ww},
+% 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}
@@ -135,16 +139,16 @@
}
\cs_new:Npn \@@_compare_aux:wn #1; #2
{
- \exp_after:wN \@@_compare_back:ww
+ \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, \@@_compare_nan:w}
+% \begin{macro}[EXP]{\@@_compare_back_any:ww, \@@_compare_back:ww, \@@_compare_nan:w}
% \begin{quote}
-% \cs{@@_compare_back:ww} \meta{y} |;| \meta{x} |;|
+% \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
@@ -157,6 +161,23 @@
% 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_any:ww #1#2; #3
+ {
+ \@@_if_type_fp:NTwFw
+ #1 { \@@_if_type_fp:NTwFw #3 \use_i:nn \s_@@ \use_ii:nn \q_stop }
+ \s_@@ \use_ii:nn \q_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 \@@_compare_back:ww
\s_@@ \@@_chk:w #1 #2 #3;
\s_@@ \@@_chk:w #4 #5 #6;
@@ -188,6 +209,46 @@
% \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 ; = 0 \exp_stop_f:
+ \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}
@@ -309,7 +370,7 @@
% \end{macro}
%
% \begin{macro}[EXP]{\fp_step_function:nnnN, \fp_step_function:nnnc}
-% \begin{macro}[EXP]{\@@_step:wwwN}
+% \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
@@ -326,6 +387,7 @@
}
\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
@@ -334,7 +396,20 @@
% progress. Conversion to decimal is done just before calling the
% user's function.
% \begin{macrocode}
-\cs_new:Npn \@@_step:wwwN #1 ; \s_@@ \@@_chk:w #2#3#4 ; #5; #6
+\cs_new:Npn \@@_step:wwwN #1#2; #3#4; #5#6; #7
+ {
+ \@@_if_type_fp:NTwFw #1 { } \s_@@ \__prg_break: \q_stop
+ \@@_if_type_fp:NTwFw #3 { } \s_@@ \__prg_break: \q_stop
+ \@@_if_type_fp:NTwFw #5 { } \s_@@ \__prg_break: \q_stop
+ \use_i:nnnn { \@@_step_fp:wwwN #1#2; #3#4; #5#6; #7 }
+ \__prg_break_point:
+ \use:n
+ {
+ \@@_error:nfff { fp-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
{
@@ -410,6 +485,8 @@
% \end{macro}
%
% \begin{macrocode}
+\__kernel_msg_new:nnn { kernel } { fp-step-tuple }
+ { Tuple~argument~in~fp_step_...~{#1}{#2}{#3}. }
\__kernel_msg_new:nnn { kernel } { fp-bad-step }
{ Invalid~step~size~#2~in~step~function~#3. }
\__kernel_msg_new:nnn { kernel } { fp-tiny-step }
@@ -511,12 +588,12 @@
%
% \subsection{Boolean operations}
%
-% \begin{macro}[EXP]{\@@_not_o:w}
+% \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:cpn { @@_not_o:w } #1 \s_@@ \@@_chk:w #2#3; @
+\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
@@ -524,11 +601,12 @@
\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+
-% \begin{macro}[EXP]+\@@_|_o:ww+
+% \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
@@ -547,9 +625,22 @@
\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#3; { \fi: #2 #1; }
+\cs_new:Npn \@@_and_return:wNw #1; \fi: #2;
+ { \fi: \@@_exp_after_o:w #1; }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -557,32 +648,28 @@
%
% \subsection{Ternary operator}
%
-%^^A todo: understand and optimize.
% \begin{macro}[EXP]
% {\@@_ternary:NwwN, \@@_ternary_auxi:NwwN, \@@_ternary_auxii:NwwN}
-% \begin{macro}[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
-% \texttt{nan}. The second function receives the output of the first
-% 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.
+% 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
+\cs_new:Npn \@@_ternary:NwwN #1 #2#3@ #4@ #5
{
- \if_meaning:w \@@_parse_infix_::N #4
- \@@_ternary_loop:Nw
- #2
- \s_@@ \@@_chk:w { \@@_ternary_loop_break:w } ;
- \@@_ternary_break_point:n { \exp_after:wN \@@_ternary_auxi:NwwN }
+ \if_meaning:w \@@_parse_infix_::N #5
+ \if_charcode:w 0
+ \@@_if_type_fp:NTwFw
+ #2 { \use_i:nn \use_i_delimit_by_q_stop:nw #3 \q_stop }
+ \s_@@ 1 \q_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 #3 \s_@@_stop
+ \@@_exp_after_array_f:w #4 \s_@@_stop
\exp_after:wN @
\exp:w
\@@_parse_operand:Nw \c_@@_prec_colon_int
@@ -593,25 +680,11 @@
\exp_after:wN \@@_parse_continue:NwN
\exp_after:wN #1
\exp:w \exp_end_continue_f:w
- \@@_exp_after_array_f:w #3 \s_@@_stop
- \exp_after:wN #4
+ \@@_exp_after_array_f:w #4 \s_@@_stop
+ \exp_after:wN #5
\exp_after:wN #1
\fi:
}
-\cs_new:Npn \@@_ternary_loop_break:w
- #1 \fi: #2 \@@_ternary_break_point:n #3
- {
- 0 = 0 \exp_stop_f: \fi:
- \exp_after:wN \@@_ternary_auxii:NwwN
- }
-\cs_new:Npn \@@_ternary_loop:Nw \s_@@ \@@_chk:w #1#2;
- {
- \if_int_compare:w #1 > 0 \exp_stop_f:
- \exp_after:wN \@@_ternary_map_break:
- \fi:
- \@@_ternary_loop:Nw
- }
-\cs_new:Npn \@@_ternary_map_break: #1 \@@_ternary_break_point:n #2 {#2}
\cs_new:Npn \@@_ternary_auxi:NwwN #1#2@#3@#4
{
\exp_after:wN \@@_parse_continue:NwN
@@ -630,7 +703,6 @@
}
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
% \begin{macrocode}
%</initex|package>