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.dtx393
1 files changed, 393 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
new file mode 100644
index 00000000000..2517236fb21
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
@@ -0,0 +1,393 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-logic.dtx Copyright (C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The released version of this bundle is available from CTAN.
+%%
+%% -----------------------------------------------------------------------
+%%
+%% The development version of the bundle can be found at
+%%
+%% http://www.latex-project.org/svnroot/experimental/trunk/
+%%
+%% for those people who are interested.
+%%
+%%%%%%%%%%%
+%% NOTE: %%
+%%%%%%%%%%%
+%%
+%% Snapshots taken from the repository represent work in progress and may
+%% not work or may contain conflicting material! We therefore ask
+%% people _not_ to put them into distributions, archives, etc. without
+%% prior consultation with the LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-logic.dtx 3504 2012-03-06 06:38:45Z bruno $
+ {L3 Floating-point conditionals}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3fp-logic} package\thanks{This file
+% has version number \ExplFileVersion, last
+% revised \ExplFileDate.}\\
+% Floating point conditionals}
+% \author{^^A
+% The \LaTeX3 Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team@latex-project.org}
+% {latex-team@latex-project.org}^^A
+% }^^A
+% }
+% \date{Released \ExplFileDate}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-logic} Implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \subsection{Existence test}
+%
+% \begin{macro}[pTF]{\fp_if_exist:N, \fp_if_exist:c}
+% Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
+% \begin{macrocode}
+\cs_new_eq:NN \fp_if_exist:NTF \cs_if_exist:NTF
+\cs_new_eq:NN \fp_if_exist:NT \cs_if_exist:NT
+\cs_new_eq:NN \fp_if_exist:NF \cs_if_exist:NF
+\cs_new_eq:NN \fp_if_exist_p:N \cs_if_exist_p:N
+\cs_new_eq:NN \fp_if_exist:cTF \cs_if_exist:cTF
+\cs_new_eq:NN \fp_if_exist:cT \cs_if_exist:cT
+\cs_new_eq:NN \fp_if_exist:cF \cs_if_exist:cF
+\cs_new_eq:NN \fp_if_exist_p:c \cs_if_exist_p:c
+% \end{macrocode}
+% \end{macro}
+%
+% \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}
+% 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}.
+% \begin{macrocode}
+\cs_new:Npn \@@_compare: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
+ \if_meaning:w #1 #4
+ \if_meaning:w 1 #1
+ \@@_compare_mantissa:ww #3; #6;
+ \else:
+ 0
+ \fi:
+ \else:
+ \if_int_compare:w #1 < #4 - \fi: 1
+ \fi:
+ \else:
+ \if_meaning:w 0 #1
+ \if_meaning:w 0 #4
+ 0
+ \else:
+ 1
+ \fi:
+ \else:
+ 1
+ \fi:
+ \fi:
+ \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;
+ {
+ \if_int_compare:w #1 = #3 \exp_stop_f:
+ \@@_compare_mantissa:nnnnnnnn #2 #4
+ \else:
+ \if_int_compare:w #1 < #3 - \fi: 1
+ \fi:
+ }
+\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:
+ \else:
+ \if_int_compare:w #2 < #6 - \fi: 1
+ \fi:
+ \else:
+ \if_int_compare:w #1 < #5 - \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 |?|.
+% \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 {#3} {#1}
+ = \__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:ww
+ \tex_romannumeral:D -`0 \@@_parse:n {#2} #1;
+ }
+% \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{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;
+ {
+ \if_meaning:w 0 #1
+ \prg_return_false:
+ \else:
+ \prg_return_true:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Boolean operations}
+%
+% \begin{macro}[int, EXP]{\@@_not: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;
+ {
+ \if_meaning:w 0 #1
+ \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:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]+\@@_&_o:ww+
+% \begin{macro}[int, EXP]+\@@_|_o:ww+
+% \begin{macro}[aux, 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}
+\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: }
+\cs_new:Npn \@@_and_return:wNw #1; \fi: #2#3; { \fi: #2 #1; }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]
+% {\@@_ternary:NwwN, \@@_ternary_i:NwwN, \@@_ternary_ii:NwwN}
+% 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.
+%^^A todo: optimize.
+% \begin{macrocode}
+\cs_new:Npn \@@_ternary:NwwN #1 #2@ #3@ #4
+ {
+ \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_i:NwwN }
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \@@_parse_exp_after_array:wf #3 \s_@@_stop
+ \exp_after:wN @
+ \tex_romannumeral:D
+ \@@_parse_until:Nw \c_two
+ \@@_parse_expand:w
+ \else:
+ \@@_error:n { Missing~':'~clause~for~'?:'. }
+ \exp_after:wN \@@_parse_until_test:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \@@_parse_exp_after_array:wf #3 \s_@@_stop
+ \exp_after:wN #4
+ \exp_after:wN #1
+ \fi:
+ }
+\cs_new:Npn \@@_ternary_loop_break:w #1 \fi: #2 \@@_ternary_break_point:n #3
+ {
+ \c_zero = \c_zero \fi:
+ \exp_after:wN \@@_ternary_ii:NwwN
+ }
+\cs_new:Npn \@@_ternary_loop:Nw \s_@@ \@@_chk:w #1#2;
+ {
+ \if_int_compare:w #1 > \c_zero
+ \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_i:NwwN #1#2@#3@#4
+ {
+ \exp_after:wN \@@_parse_until_test:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \@@_parse_exp_after_array:wf #2 \s_@@_stop
+ #4 #1
+ }
+\cs_new:Npn \@@_ternary_ii:NwwN #1#2@#3@#4
+ {
+ \exp_after:wN \@@_parse_until_test:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \@@_parse_exp_after_array:wf #3 \s_@@_stop
+ #4 #1
+ }
+% \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}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file