summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx301
1 files changed, 135 insertions, 166 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
index de3bae56fd4..8d2a67dc46e 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
@@ -22,9 +22,8 @@
%
%<*driver>
\documentclass[full]{l3doc}
-\GetIdInfo$Id: l3fp-aux.dtx 6968 2017-02-20 16:08:44Z bruno $
- {L3 Floating-point support functions}
-\documentclass[full]{l3doc}
+\def\ExplFileDate{2017/03/18}
+\def\ExplFileVersion{7019}
\begin{document}
\DocInput{\jobname.dtx}
\end{document}
@@ -68,7 +67,6 @@
%
% ^^A todo: make sanitize and pack more homogeneous between modules.
%
-% ^^A begin[todo]: move
% \subsection{Internal representation}
%
% Internally, a floating point number \meta{X} is a
@@ -79,25 +77,21 @@
% Let us explain each piece separately.
%
% Internal floating point numbers will be used in expressions,
-% and in this context will be subject to f-expansion. They must
+% and in this context will be subject to \texttt{f}-expansion. They must
% leave a recognizable mark after \texttt{f}-expansion, to prevent the
% floating point number from being re-parsed. Thus, \cs{s_@@}
% is simply another name for \tn{relax}.
%
-% Since floating point numbers are always accessed by the various
-% operations using f-expansion, we can safely let them be protected:
-% \texttt{x}-expansion will then leave them untouched. However, when
-% used directly without an accessor function, floating points should
-% produce an error. \cs{s_@@} will do nothing, and \cs{@@_chk:w}
-% produces an error.
-%
-% The (decimal part of the) IEEE-754-2008 standard requires the
-% format to be able to represent special floating point numbers
-% besides the usual positive and negative cases. The various
-% possibilities will be distinguished by their \meta{case}, which
-% is a single digit:\footnote{Bruno: I need to implement subnormal
-% numbers. Also, quiet and signalling \texttt{nan} must be better
-% distinguished.}
+% When used directly without an accessor function, floating points
+% should produce an error: this is the role of \cs{@@_chk:w}. We could
+% make floating point variables be protected to prevent them from
+% expanding under \texttt{x}-expansion, but it seems more convenient to
+% treat them as a subcase of token list variables.
+%
+% The (decimal part of the) IEEE-754-2008 standard requires the format
+% to be able to represent special floating point numbers besides the
+% usual positive and negative cases. We distinguish the various
+% possibilities by their \meta{case}, which is a single digit:
% \begin{itemize}
% \item[0] zeros: |+0| and |-0|,
% \item[1] \enquote{normal} numbers (positive and negative),
@@ -121,19 +115,16 @@
% \cs{s_@@} \cs{@@_chk:w} 1 \meta{sign} \Arg{exponent}
% \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} |;|
% \end{quote}
-% Here, the \meta{exponent} is an integer, at most
-% $\cs{c_@@_max_exponent_int} =
-% \the\csname\detokenize{c__fp_max_exponent_int}\endcsname$
-% in absolute value. The body consists in four
-% blocks of exactly $4$ digits, $ 0000 \leq \meta{X_i} \leq 9999$,
-% such that
+% Here, the \meta{exponent} is an integer, between
+% $-\ExplSyntaxOn\int_use:N\c__fp_minus_min_exponent_int$ and
+% $\ExplSyntaxOn\int_use:N\c__fp_max_exponent_int$. The body consists
+% in four blocks of exactly $4$ digits,
+% $0000 \leq \meta{X_i} \leq 9999$, and the floating point is
% \[
-% \meta{X}
-% = (-1)^{\meta{sign}} 10^{-\meta{exponent}}
-% \sum_{i=1}^{4} \meta{X_i} 10^{-4i}
+% (-1)^{\meta{sign}/2} \meta{X_1}\meta{X_2}\meta{X_3}\meta{X_4}\cdot 10^{\meta{exponent}-16}
% \]
-% and such that the \meta{exponent} is minimal. This implies
-% $ 1000 \leq \meta{X_1} \leq 9999 $.
+% where we have concatenated the $16$ digits. Currently, floating point numbers are normalized such that
+% the \meta{exponent} is minimal, in other words, $1000 \leq \meta{X_1} \leq 9999$.
%
% \begin{table}\centering
% \caption{Internal representation of floating point numbers.}
@@ -156,30 +147,7 @@
% \end{tabular}
% \end{table}
%
-% \subsection{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]
+% Calculations are done in base $10000$, \emph{i.e.} one myriad.
%
% \subsection{Using arguments and semicolons}
%
@@ -212,7 +180,6 @@
% \end{macrocode}
% \end{macro}
%
-% ^^A todo: rename to \@@_args_swap:Nww
% \begin{macro}[int, EXP]{\@@_reverse_args:Nww}
% Many internal functions take arguments delimited by semicolons, and
% it is occasionally useful to swap two such arguments.
@@ -223,7 +190,7 @@
%
% \begin{macro}[int, EXP]{\@@_rrot:www}
% Rotate three arguments delimited by semicolons. This is the inverse
-% (or the square) of the Forth primitive |ROT|.
+% (or the square) of the Forth primitive |ROT|, hence the name.
% \begin{macrocode}
\cs_new:Npn \@@_rrot:www #1; #2; #3; { #2; #3; #1; }
% \end{macrocode}
@@ -284,14 +251,7 @@
%
% \begin{variable}
% {\c_zero_fp, \c_minus_zero_fp, \c_inf_fp, \c_minus_inf_fp, \c_nan_fp}
-% The special floating points. All of them have the form
-% \begin{quote}
-% \cs{s_@@} \cs{@@_chk:w} \meta{case} \meta{sign} \cs[no-index]{s_@@_\ldots} |;|
-% \end{quote}
-% where the dots in \cs[no-index]{s_@@_\ldots} are one of \texttt{invalid},
-% \texttt{underflow}, \texttt{overflow}, \texttt{division},
-% \texttt{exact}, describing how the floating point was created. We
-% define the floating points here as \enquote{exact}.
+% The special floating points. We define the floating points here as \enquote{exact}.
% \begin{macrocode}
\tl_const:Nn \c_zero_fp { \s_@@ \@@_chk:w 0 0 \s_@@_exact ; }
\tl_const:Nn \c_minus_zero_fp { \s_@@ \@@_chk:w 0 2 \s_@@_exact ; }
@@ -317,20 +277,15 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}[int]{\c_@@_max_exponent_int}
-% Normal floating point numbers have an exponent at most
-% \texttt{max_exponent} in absolute value. Larger numbers are rounded
-% to $\pm\infty$. Smaller numbers are subnormal (not implemented yet),
-% and digits beyond
-% $10^{-\text{\texttt{max_exponent}}}$ are rounded away, hence the
-% true minimum exponent is $-\text{\texttt{max_exponent}}-16$;
-% beyond this, numbers are rounded to zero. Why this choice of
-% limits? When computing $(a\cdot 10^n)^(b\cdot 10^p)$, we need to
-% evaluate $\log(a\cdot 10^n) = \log(a) + n \log(10)$ as a fixed point
-% number, which we manipulate as blocks of $4$ digits. Multiplying
-% such a fixed point number by $n<10000$ is much cheaper than larger
-% $n$, because we can multiply $n$ with each block safely.
+% \begin{variable}[int]{\c_@@_minus_min_exponent_int, \c_@@_max_exponent_int}
+% Normal floating point numbers have an exponent between $-$
+% \texttt{minus_min_exponent} and \texttt{max_exponent} inclusive.
+% Larger numbers are rounded to $\pm\infty$. Smaller numbers are
+% rounded to $\pm 0$. It would be more natural to define a
+% \texttt{min_exponent} with the opposite sign but that would waste
+% one \TeX{} count.
% \begin{macrocode}
+\int_const:Nn \c_@@_minus_min_exponent_int { 10000 }
\int_const:Nn \c_@@_max_exponent_int { 10000 }
% \end{macrocode}
% \end{variable}
@@ -343,6 +298,20 @@
% \end{macrocode}
% \end{variable}
%
+% \begin{variable}{\c_@@_overflowing_fp}
+% A floating point number that is bigger than all normal floating
+% point numbers. This replaces infinities when converting to formats
+% that do not support infinities.
+% \begin{macrocode}
+\tl_const:Nx \c_@@_overflowing_fp
+ {
+ \s_@@ \@@_chk:w 1 0
+ { \int_eval:n { \c_@@_max_exponent_int + 1 } }
+ {1000} {0000} {0000} {0000} ;
+ }
+% \end{macrocode}
+% \end{variable}
+%
% \begin{macro}[int, EXP]{\@@_zero_fp:N, \@@_inf_fp:N}
% In case of overflow or underflow, we have to output
% a zero or infinity with a given sign.
@@ -354,29 +323,9 @@
% \end{macrocode}
% \end{macro}
%
-%^^A todo: currently unused.
-% \begin{macro}[int, EXP]{\@@_max_fp:N, \@@_min_fp:N}
-% In some cases, we need to output the smallest or biggest positive or
-% negative finite numbers.
-% \begin{macrocode}
-\cs_new:Npn \@@_min_fp:N #1
- {
- \s_@@ \@@_chk:w 1 #1
- { \int_eval:n { - \c_@@_max_exponent_int } }
- {1000} {0000} {0000} {0000} ;
- }
-\cs_new:Npn \@@_max_fp:N #1
- {
- \s_@@ \@@_chk:w 1 #1
- { \int_use:N \c_@@_max_exponent_int }
- {9999} {9999} {9999} {9999} ;
- }
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}[int, EXP]{\@@_exponent:w}
% For normal numbers, the function expands to the exponent, otherwise
-% to $0$.
+% to $0$. This is used in \pkg{l3str-format}.
% \begin{macrocode}
\cs_new:Npn \@@_exponent:w \s_@@ \@@_chk:w #1
{
@@ -416,8 +365,8 @@
{
\if_case:w
\if_int_compare:w #2 > \c_@@_max_exponent_int 1 ~ \else:
- \if_int_compare:w #2 < - \c_@@_max_exponent_int 2 ~ \else:
- \if_meaning:w 1 #1 3 ~ \else: 0 ~ \fi: \fi: \fi:
+ \if_int_compare:w #2 < - \c_@@_minus_min_exponent_int 2 ~ \else:
+ \if_meaning:w 1 #1 3 ~ \fi: \fi: \fi: 0 ~
\or: \exp_after:wN \@@_overflow:w
\or: \exp_after:wN \@@_underflow:w
\or: \exp_after:wN \@@_sanitize_zero:w
@@ -433,11 +382,11 @@
%
% \subsection{Expanding after a floating point number}
%
-% ^^A todo: maybe delete \cs{@@_exp_after_o:nw}?
% \begin{macro}[int, EXP]{\@@_exp_after_o:w}
-% \begin{macro}[int, EXP]{\@@_exp_after_o:nw, \@@_exp_after_f:nw}
+% \begin{macro}[int, EXP]{\@@_exp_after_f:nw}
% \begin{syntax}
-% \cs{@@_exp_after_o:nw} \Arg{tokens} \meta{floating point} \meta{more tokens}
+% \cs{@@_exp_after_o:w} \meta{floating point}
+% \cs{@@_exp_after_f:nw} \Arg{tokens} \meta{floating point}
% \end{syntax}
% Places \meta{tokens} (empty in the case of \cs{@@_exp_after_o:w})
% between the \meta{floating point} and the \meta{more tokens}, then
@@ -458,16 +407,6 @@
{ }
#1
}
-\cs_new:Npn \@@_exp_after_o:nw #1 \s_@@ \@@_chk:w #2
- {
- \if_meaning:w 1 #2
- \exp_after:wN \@@_exp_after_normal:nNNw
- \else:
- \exp_after:wN \@@_exp_after_special:nNNw
- \fi:
- { #1 }
- #2
- }
\cs_new:Npn \@@_exp_after_f:nw #1 \s_@@ \@@_chk:w #2
{
\if_meaning:w 1 #2
@@ -697,6 +636,58 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[aux, EXP]
+% {
+% \@@_basics_pack_low:NNNNNw,
+% \@@_basics_pack_high:NNNNNw,
+% \@@_basics_pack_high_carry:w
+% }
+% Addition and multiplication of significands 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. 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}|.
+%
+% This is used in \pkg{l3fp-basics} and \pkg{l3fp-extended}.
+% \begin{macrocode}
+\cs_new:Npn \@@_basics_pack_low:NNNNNw #1 #2#3#4#5 #6;
+ { + #1 - 1 ; {#2#3#4#5} {#6} ; }
+\cs_new:Npn \@@_basics_pack_high:NNNNNw #1 #2#3#4#5 #6;
+ {
+ \if_meaning:w 2 #1
+ \@@_basics_pack_high_carry:w
+ \fi:
+ ; {#2#3#4#5} {#6}
+ }
+\cs_new:Npn \@@_basics_pack_high_carry:w \fi: ; #1
+ { \fi: + 1 ; {1000} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]
+% {
+% \@@_basics_pack_weird_low:NNNNw,
+% \@@_basics_pack_weird_high:NNNNNNNNw
+% }
+% This is used in \pkg{l3fp-basics} for additions and
+% divisions. Their syntax is confusing, hence the name.
+% \begin{macrocode}
+\cs_new:Npn \@@_basics_pack_weird_low:NNNNw #1 #2#3#4 #5;
+ {
+ \if_meaning:w 2 #1
+ + 1
+ \fi:
+ \__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{Decimate (dividing by a power of 10)}
%
% ^^A begin[todo]
@@ -711,7 +702,7 @@
% \begin{syntax}
% \meta{f_1} \meta{rounding} \Arg{X'_1} \Arg{X'_2} \meta{extra-digits} |;|
% \end{syntax}
-% where $0\leq\meta{X'_i}<10^{8}-1$ are $8$ digit numbers,
+% where $0\leq\meta{X'_i}<10^{8}-1$ are $8$ digit integers,
% forming the truncation of our number. In other words,
% \[
% \left(
@@ -727,15 +718,15 @@
% is the (non-$0$, non-$5$) digit closest to $10^{17}$ times the
% difference. In particular, if the shift is $17$ or more, all
% the digits are dropped, \meta{rounding} is $1$ (not $0$), and
-% \meta{X'_1} \meta{X'_2} are both zero.
+% \meta{X'_1} and \meta{X'_2} are both zero.
%
% If the shift is $1$, the \meta{rounding} digit is simply the
% only digit that was pushed out of the brace groups (this is
% important for subtraction). It would be more natural for the
-% \meta{rounding} digit to be placed after the \meta{X_i},
+% \meta{rounding} digit to be placed after the \meta{X'_i},
% but the choice we make involves less reshuffling.
%
-% Note that this function fails for negative \meta{shift}.
+% Note that this function treats negative \meta{shift} as $0$.
% \begin{macrocode}
\cs_new:Npn \@@_decimate:nNnnnn #1
{
@@ -939,39 +930,28 @@
% \subsection{Integer floating points}
%
% \begin{macro}[int, EXP, pTF]{\@@_int:w}
-% \begin{macro}[aux, EXP]{\@@_int_normal:nnnnn, \@@_int_test:Nw}
-% Tests if the floating point argument is an integer. This holds if
-% the rounding digit resulting from \cs{@@_decimate:nNnnnn} is~$0$.
+% Tests if the floating point argument is an integer. For normal
+% floating point numbers, this holds if the rounding digit resulting
+% from \cs{@@_decimate:nNnnnn} is~$0$.
% \begin{macrocode}
-\prg_new_conditional:Npnn \@@_int:w \s_@@ \@@_chk:w #1 #2 #3; { TF , T , F , p }
+\prg_new_conditional:Npnn \@@_int:w \s_@@ \@@_chk:w #1 #2 #3 #4;
+ { TF , T , F , p }
{
\if_case:w #1 \exp_stop_f:
\prg_return_true:
- \or: \@@_int_normal:nnnnn #3
+ \or:
+ \if_charcode:w 0
+ \@@_decimate:nNnnnn { \c_@@_prec_int - #3 }
+ \@@_use_i_until_s:nw #4
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
\else: \prg_return_false:
\fi:
}
-\cs_new:Npn \@@_int_normal:nnnnn #1 #2#3#4#5
- {
- \if_int_compare:w #1 > 0 \exp_stop_f:
- \@@_decimate:nNnnnn { \c_@@_prec_int - #1 }
- \@@_int_test:Nw
- {#2} {#3} {#4} {#5}
- \else:
- \prg_return_false:
- \fi:
- }
-\cs_new:Npn \@@_int_test:Nw #1#2;
- {
- \if_meaning:w 0 #1
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
% \subsection{Small integer floating points}
%
@@ -985,20 +965,13 @@
% Tests if the floating point argument is an integer or $\pm\infty$.
% If so, it is converted to an integer in the range $[-10^{8},10^{8}]$
% and fed as a braced argument to the \meta{true code}.
-% Otherwise, the \meta{false code} is performed. First filter special
-% cases: neither \texttt{nan} nor infinities are integers. Normal
-% numbers with a non-positive exponent are never integers. When the
-% exponent is greater than $8$, the number is too large for the range.
-% Otherwise, decimate, and test the digits after the decimal
-% separator. The \cs{use_iii:nnn} remove a trailing |;| and the true
-% branch, leaving only the false branch. The \cs{__int_value:w}
-% 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. 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.
+% Otherwise, the \meta{false code} is performed.
+%
+% First filter special cases: zeros and infinities are integers,
+% \texttt{nan} is not. For normal numbers, decimate. If the rounding
+% digit is not $0$ run the \meta{false code}. If it is, then the
+% integer is |#2| |#3|; use |#3| if |#2| vanishes and otherwise
+% $10^{8}$.
% \begin{macrocode}
\cs_new:Npn \@@_small_int:wTF \s_@@ \@@_chk:w #1#2
{
@@ -1018,27 +991,23 @@
\cs_new:Npn \@@_small_int_true:wTF #1; #2#3 { #2 {#1} }
\cs_new:Npn \@@_small_int_normal:NnwTF #1#2#3;
{
- \if_int_compare:w #2 > 0 \exp_stop_f:
- \@@_decimate:nNnnnn { \c_@@_prec_int - #2 }
- \@@_small_int_test:NnnwNnw
- #3 #1 {#2}
- \else:
- \exp_after:wN \use_iii:nnn
- \fi:
- ;
+ \@@_decimate:nNnnnn { \c_@@_prec_int - #2 }
+ \@@_small_int_test:NnnwNw
+ #3 #1
}
-\cs_new:Npn \@@_small_int_test:NnnwNnw #1#2#3#4; #5#6
+\cs_new:Npn \@@_small_int_test:NnnwNw #1#2#3#4; #5
{
\if_meaning:w 0 #1
\exp_after:wN \@@_small_int_true:wTF
\__int_value:w \if_meaning:w 2 #5 - \fi:
- \if_int_compare:w #6 > \c_@@_half_prec_int
+ \if_int_compare:w #2 > 0 \exp_stop_f:
1 0000 0000
\else:
#3
\fi:
+ \exp_after:wN ;
\else:
- \use_i:nn
+ \exp_after:wN \use_ii:nn
\fi:
}
% \end{macrocode}