summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2012-07-23 17:15:00 +0000
committerKarl Berry <karl@freefriends.org>2012-07-23 17:15:00 +0000
commit134349701bddf7cbbacf6030c6b9f9838aff96fa (patch)
treeec1140c46e1c0347a671a6fa3cf8af5a79e95f93 /Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
parentf7855c12c18bb97b7b9e49ab685ee558d8c0b47b (diff)
l3kernel 3990 (17jul12)
git-svn-id: svn://tug.org/texlive/trunk@27108 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx1634
1 files changed, 1634 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
new file mode 100644
index 00000000000..0b06d377232
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
@@ -0,0 +1,1634 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-basics.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-basics.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Floating-point arithmetic}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3fp-basics} package\thanks{This file
+% has version number \ExplFileVersion, last
+% revised \ExplFileDate.}\\
+% Floating point arithmetic}
+% \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-basics} Implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% 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]
+%
+% 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.
+%
+% \subsection{Common to several operations}
+%
+% \begin{macro}[EXP]
+% {
+% \@@_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$.
+% \begin{macrocode}
+\cs_new:Npn \@@_basics_pack_low:NNNNNw #1 #2#3#4#5 #6;
+ {
+ \if_meaning:w 2 #1
+ + \c_one
+ \fi:
+ ; {#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: + \c_one ; {1000} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_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
+% }
+% \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.
+% \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;
+ {
+ \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
+ \fi:
+ 3 3 #1 #2
+ }
+% \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}
+%
+% \begin{macro}[int, EXP]{\@@_-_o:ww}
+% Change the sign of the second argument.
+% \begin{macrocode}
+\cs_new:cpn { @@_-_o:ww }
+ \s_@@ \@@_chk:w #1 #2 #3 ; \s_@@ \@@_chk:w #4 #5
+ {
+ \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 ;
+ }
+% \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{macrocode}
+\cs_new:Npn \@@_add_cases:NN #1 #2
+ {
+ \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
+ \else:
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_basics_return_i:NNNNww
+ \fi:
+ \exp_after:wN #1
+ \fi:
+ #2
+ }
+% \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}.
+% \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:
+ }
+% \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.}
+% \begin{macrocode}
+\cs_new:Npn \@@_add_zeros:NNww #1#2 #3;
+ {
+ \if_int_compare:w #1 #2 = 02 \exp_stop_f:
+ \@@_case_return_o:Nw \c_zero_fp
+ \else:
+ \@@_case_return_same_o:w
+ \fi:
+ \s_@@ \@@_chk:w 0 #2
+ }
+% \end{macrocode}
+% If both infinities have the same sign, just return that infinity,
+% otherwise, it is an invalid operation.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_inf:NNww #1#2 #3;
+ {
+ \if_meaning:w #1 #2
+ \@@_case_return_same_o:w
+ \else:
+ \@@_case_use:nw
+ {
+ \@@_invalid_operation:Nnww \c_nan_fp { + }
+ \s_@@ \@@_chk:w 2 #1 #3 ;
+ }
+ \fi:
+ \s_@@ \@@_chk:w 2 #2
+ }
+% \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}
+% 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
+ {
+ \if_meaning:w #1#2
+ \exp_after:wN \@@_add_npos:Nnwnw
+ \else:
+ \exp_after:wN \@@_sub_npos:Nnwnw
+ \fi:
+ #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Absolute addition}
+%
+% 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{macrocode}
+\cs_new:Npn \@@_add_npos:Nnwnw #1 #2#3; #4
+ {
+ \exp_after:wN \@@_sanitize:Nw
+ \exp_after:wN #1
+ \int_use:N \__int_eval:w
+ \if_int_compare:w #2 > #4 \exp_stop_f:
+ #2
+ \exp_after:wN \@@_add_big_i:wNww \__int_value:w -
+ \else:
+ #4
+ \exp_after:wN \@@_add_big_ii:wNww \__int_value:w
+ \fi:
+ \__int_eval:w #4 - #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{macrocode}
+\cs_new:Npn \@@_add_big_i:wNww #1; #2 #3; #4;
+ {
+ \@@_decimate:nNnnnn {#1}
+ \@@_add_mantissa:NnnwnnnnN
+ #4
+ #3
+ #2
+ }
+\cs_new:Npn \@@_add_big_ii:wNww #1; #2 #3; #4;
+ {
+ \@@_decimate:nNnnnn {#1}
+ \@@_add_mantissa:NnnwnnnnN
+ #3
+ #4
+ #2
+ }
+% \end{macrocode}
+% \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}
+% 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
+% now and check for a carry, then go back and do the rounding.
+% The rounding may cause a carry in very rare cases such as
+% $0.99\cdots 95 \to 1.00\cdots 0$, but this situation always
+% 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
+ {
+ \exp_after:wN \@@_add_mantissa_test: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
+ + \c_one
+ \fi:
+ ; #2 #3 #4 #5 #6 #7 ;
+ }
+\cs_new:Npn \@@_add_mantissa_test:N #1
+ {
+ \if:w 2 #1
+ \exp_after:wN \@@_add_mantissa_carry:wwNNNN
+ \else:
+ \exp_after:wN \@@_add_mantissa_no_carry:wwNNNN
+ \fi:
+ }
+% \end{macrocode}
+%
+% \begin{quote}
+% \cs{@@_add_mantissa_no_carry:wwNNNN}
+% ~~\meta{8d} |;| \meta{6d} |;| \meta{2d} |;|
+% ~~\meta{rounding} \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.}
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_add_mantissa_no_carry:wwNNNN
+ #1; #2; #3#4 ; #5#6
+ {
+ \exp_after:wN \@@_basics_pack_high:NNNNNw
+ \int_use:N \__int_eval:w 1 #1
+ \exp_after:wN \@@_basics_pack_low:NNNNNw
+ \int_use:N \__int_eval:w 1 #2 #3#4
+ + \@@_round:NNN #6 #4 #5
+ \exp_after:wN ;
+ }
+% \end{macrocode}
+%
+% 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{quote}
+% \cs{@@_add_mantissa_carry:wwNNNN}
+% ~~\meta{8d} |;| \meta{6d} |;| \meta{2d} |;|
+% ~~\meta{rounding} \meta{sign}
+% \end{quote}
+% \begin{macrocode}
+\cs_new:Npn \@@_add_mantissa_carry:wwNNNN
+ #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 ;
+ }
+\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{macrocode}
+\cs_new:Npn \@@_sub_npos:Nnwnw #1 #2#3; #4 #5;
+ {
+ \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;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_sub_exponent_eq:nnnnnnnn}
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_exponent_eq:nnnnnnnn #1#2#3#4 #5#6#7#8
+ {
+ \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
+ \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:
+ \fi:
+ \fi:
+ }
+\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{macrocode}
+\cs_new:Npn \@@_sub_big_i:wNww #1; #2 #3; #4;
+ {
+ \@@_decimate:nNnnnn {#1}
+ \@@_sub_back_mantissa:NnnwNnnnn
+ #4
+ #2
+ #3
+ }
+\cs_new:Npn \@@_sub_big_ii:wNww #1; #2 #3; #4;
+ {
+ \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;
+ }
+% \end{macrocode}
+% \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{macrocode}
+\cs_new:Npn \@@_sub_back_mantissa:NnnwNnnnn #1 #2#3 #4; #5 #6#7#8#9
+ {
+ \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
+ }
+% \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
+ {
+ \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
+ \exp_after:wN ;
+ }
+\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} ; }
+% \end{macrocode}
+% \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{macrocode}
+\cs_new:Npn \@@_sub_back_mantissa_i:NNwNNNNwN #1#2 #3 #4#5#6#7 #8; #9
+ {
+ \if:w 0 #4
+ \exp_after:wN \@@_sub_back_carry:NNwNnnnn
+ \exp_after:wN #1
+ \exp_after:wN #9
+ \fi:
+ ; #2
+ {#4#5#6#7} {#8}
+ }
+% \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{macrocode}
+\cs_new:Npn \@@_sub_back_carry:NNwNnnnn #1#2 ; #3 #4#5#6#7 ;
+ {
+ \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
+ }
+% \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 ;
+ {
+ \if:w 0 #1
+ - 8
+ \exp_after:wN \@@_sub_back_carry_small:wN \__int_value:w
+ \else:
+ - \@@_sub_back_carry_ii:NNNNNNNNw #1 1234567;
+ \exp_after:wN \@@_sub_back_carry_large:NNNNNNNNw
+ \fi:
+ #1
+ }
+% \end{macrocode}
+% The case where the number is non-zero is slightly easier.
+% \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;
+ {
+ \@@_sub_back_carry_large_ii:NNNNNNNNw
+ #9 000000 ; {#1#2#3#4} {#5#6#7#8}
+ }
+\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.
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_back_carry_small:wN #1;
+ {
+ - \exp_after:wN \@@_use_i_until_s:nw
+ \use_none:nnnnnnnnn #1 012345678;
+ \@@_sub_back_carry_small_ii:NNNNNNNN #1 00000000 ;
+ }
+\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}
+%
+%
+% \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{macrocode}
+\cs_new:Npn \@@_mul_cases:NN #1 #2
+ {
+ \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 ;
+ }
+% \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{macrocode}
+\cs_new:Npn \@@_mul_normal:NNww #1#2
+ {
+ \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
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Absolute multiplication}
+%
+% 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{macrocode}
+\cs_new:Npn \@@_mul_npos:Nnwnw #1 #2#3; #4 #5;
+ {
+ \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 ;
+ }
+% \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{;}).
+%
+% The product of two $16$ digit integers has $31$ or $32$ digits,
+% but it is impossible to know which one before computing. The place
+% where we round depends on that number of digits, and may depend
+% on all digits until the last in some rare cases. The approach is
+% thus to compute the $5$ first blocks of $4$ digits (the first one
+% is between $100$ and $9999$ inclusive), and a compact version of
+% the remaining $3$ blocks. Afterwards, the number of digits is
+% 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
+ {
+ \exp_after:wN \@@_mul_mantissa_after:NNN
+ \exp_after:wN #5
+ \int_use:N \__int_eval:w 99990000 + #1*#6 +
+ \exp_after:wN \@@_mul_mantissa_keep:NNNNNw
+ \int_use:N \__int_eval:w 99990000 + #1*#7 + #2*#6 +
+ \exp_after:wN \@@_mul_mantissa_keep:NNNNNw
+ \int_use:N \__int_eval:w 99990000 + #1*#8 + #2*#7 + #3*#6 +
+ \exp_after:wN \@@_mul_mantissa_drop:NNNNNw
+ \int_use:N \__int_eval:w 99990000 + #1*#9 + #2*#8 + #3*#7 + #4*#6 +
+ \exp_after:wN \@@_mul_mantissa_drop:NNNNNw
+ \int_use:N \__int_eval:w 99990000 + #2*#9 + #3*#8 + #4*#7 +
+ \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 ;
+ }
+\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
+% \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} |;|
+% \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
+% 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.
+% \begin{macrocode}
+\cs_new:Npn \@@_mul_mantissa_after:NNN #1 #2 #3
+ {
+ \if:w 0 #3
+ \exp_after:wN \@@_mul_mantissa_small:NNwwwN
+ \else:
+ \exp_after:wN \@@_mul_mantissa_large:NwwNNNN
+ \fi:
+ #1 #3
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_mul_mantissa_large: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.
+% \begin{macrocode}
+\cs_new:Npn \@@_mul_mantissa_large: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
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_mul_mantissa_small: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.
+% \begin{macrocode}
+\cs_new:Npn \@@_mul_mantissa_small:NNwwwN #1 #2#3; #4; #5; + #6
+ {
+ - \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} ;
+ }
+% \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}
+%
+% \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{macrocode}
+\cs_new:Npn \@@_div_back_normal:NNww #1#2
+ {
+ \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:
+ }
+% \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{macrocode}
+\cs_new:Npn \@@_div_back_npos:Nnwnw #1 #2 #3#4#5#6; #7 #8;
+ {
+ \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
+ }
+% \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
+% 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
+% \[
+% \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{ 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
+% \[
+% 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
+% &=
+% 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
+% \\
+% &<
+% A_{1}A_{2}0
+% \cdot \left( 1 - 10 \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{3}{2} y + 10
+% \\
+% &\leq
+% \frac{A_{1}A_{2}0}{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
+% \[
+% 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{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
+% < 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}
+% \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}
+% \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.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_ii:ww #1; #2;
+ {
+ \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 ;
+ }
+% \end{macrocode}
+% \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}
+% \end{quote}
+% The goal here is to expand 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}
+% \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.
+%
+% 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 ).
+% \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.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_calc:Nwwnnnnnn 1#1#2; #3;#4#5 #6#7#8#9
+ {
+ 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}
+ }
+\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;
+ {
+ \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 ;
+ }
+% \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;
+ {
+ \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 ;
+ }
+% \end{macrocode}
+% \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}
+% \end{quote}
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_v:www #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 ;
+ }
+% \end{macrocode}
+% \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}
+% \end{quote}
+% We compute $P$ by rounding $2 E_{1} E_{2}/Z_{1}Z_{2}$.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_vi:wwnnnn #1; #2;#3#4 #5#6
+ {
+ \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}
+ }
+% \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$.
+% \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}
+% \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.
+% \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$.
+% \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.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_vii:wwnnnnnn #1; #2;#3#4 #5#6#7#8
+ {
+ + \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 ; ;
+ }
+\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;
+ {
+ \if_meaning:w 0 #1
+ \exp_after:wN \@@_div_mantissa_x:w
+ \int_use:N \__int_eval:w #3
+ \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
+ \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.
+% \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_pack:NNN}
+% $10^7 + 10\cdot Q_{4} + 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.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_pack:NNN 1 #1 #2 { + #1 #2 ; }
+% \end{macrocode}
+% Once those have been expanded, we get
+% \begin{quote}
+% \cs{@@_div_mantissa_iii_after: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.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_iii_after:w 10 #1
+ {
+ \if_meaning:w 0 #1
+ \exp_after:wN \@@_div_mantissa_small:wwwNNNNwN
+ \else:
+ \exp_after:wN \@@_div_mantissa_large:wwwNNNNwN
+ \fi:
+ #1
+ }
+% \end{macrocode}
+% \begin{quote}
+% \cs{@@_div_mantissa_small:wwwNNNNwN} |0| \meta{4d} |;|
+% ~~\meta{4d} |;| \meta{4d} |;| \meta{5d} |;| \meta{sign}
+% \end{quote}
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_small:wwwNNNNwN
+ 0 #1; #2; #3; #4#5#6#7#8; #9
+ {
+ \exp_after:wN \@@_basics_pack_high:NNNNNw
+ \int_use:N \__int_eval:w 1 #1#2
+ \exp_after:wN \@@_basics_pack_low:NNNNNw
+ \int_use:N \__int_eval:w 1 #3#4#5#6#7
+ + \@@_round:NNN #9 #7 #8
+ \exp_after:wN ;
+ }
+% \end{macrocode}
+% \begin{quote}
+% \cs{@@_div_mantissa_large:wwwNNNNwN} \meta{5d} |;|
+% ~~\meta{4d} |;| \meta{4d} |;| \meta{5d} |;| \meta{sign}
+% \end{quote}
+% \footnote{Bruno: rename the \enquote{add mantissa carry pack} function.}
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_large: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 ;
+ }
+\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{macrocode}
+\cs_new:Npn \@@_neg: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_use:N \__int_eval:w \c_two - #2 \__int_eval_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_abs: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}.
+% \begin{macrocode}
+\cs_new:Npn \@@_abs:w \s_@@ \@@_chk:w #1 #2
+ { \@@_exp_after_o:w \s_@@ \@@_chk:w #1 0 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file