summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2010-07-11 22:45:31 +0000
committerKarl Berry <karl@freefriends.org>2010-07-11 22:45:31 +0000
commit6167f82118ec565f0cc686d68fc7bece5e8dbb9b (patch)
tree14480d123d1a57300328cf6c72859ee5f2b84eb3 /Master/texmf-dist/source/latex
parentf45de8d35920fc84870bf4e4fc527dbcaa3973b3 (diff)
expl3 1981 (11jul10)
git-svn-id: svn://tug.org/texlive/trunk@19383 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex')
-rw-r--r--Master/texmf-dist/source/latex/expl3/expl3.dtx5
-rw-r--r--Master/texmf-dist/source/latex/expl3/l3candidates.dtx2
-rw-r--r--Master/texmf-dist/source/latex/expl3/l3expan.dtx20
-rw-r--r--Master/texmf-dist/source/latex/expl3/l3fp.dtx2393
-rw-r--r--Master/texmf-dist/source/latex/expl3/l3intexpr.dtx25
-rw-r--r--Master/texmf-dist/source/latex/expl3/l3names.dtx20
6 files changed, 2453 insertions, 12 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/expl3.dtx b/Master/texmf-dist/source/latex/expl3/expl3.dtx
index 63fb9616c72..b063be947dc 100644
--- a/Master/texmf-dist/source/latex/expl3/expl3.dtx
+++ b/Master/texmf-dist/source/latex/expl3/expl3.dtx
@@ -37,7 +37,7 @@
\RequirePackage{l3names}
%</driver|package>
%\fi
-\GetIdInfo$Id: expl3.dtx 1905 2010-05-19 07:45:31Z joseph $
+\GetIdInfo$Id: expl3.dtx 1955 2010-06-15 06:04:59Z joseph $
{L3 Experimental code bundle wrapper}%
%\iffalse
%<*driver>
@@ -919,7 +919,8 @@
l3precom,
l3calc,
l3xref,
- l3file
+ l3file,
+ l3fp,
}
% \end{macrocode}
%
diff --git a/Master/texmf-dist/source/latex/expl3/l3candidates.dtx b/Master/texmf-dist/source/latex/expl3/l3candidates.dtx
index 2c8d8968e6c..8051fb7f340 100644
--- a/Master/texmf-dist/source/latex/expl3/l3candidates.dtx
+++ b/Master/texmf-dist/source/latex/expl3/l3candidates.dtx
@@ -37,7 +37,7 @@
%</driver|package>
%\fi
\errorcontextlines=999
-\GetIdInfo$Id$
+\GetIdInfo$Id: l3candidates.dtx 1957 2010-06-15 06:33:43Z mittelba $
{L3 Experimental 'extras' module}
%\iffalse
%<*driver>
diff --git a/Master/texmf-dist/source/latex/expl3/l3expan.dtx b/Master/texmf-dist/source/latex/expl3/l3expan.dtx
index 1a77ea97d71..e28b81baa32 100644
--- a/Master/texmf-dist/source/latex/expl3/l3expan.dtx
+++ b/Master/texmf-dist/source/latex/expl3/l3expan.dtx
@@ -36,7 +36,7 @@
\RequirePackage{l3names}
%</driver|package>
%\fi
-\GetIdInfo$Id: l3expan.dtx 1873 2010-03-24 08:32:54Z joseph $
+\GetIdInfo$Id: l3expan.dtx 1948 2010-06-10 18:53:09Z joseph $
{L3 Experimental Argument Expansion module}
%\iffalse
%<*driver>
@@ -440,10 +440,12 @@
% \begin{function}{
% \exp_last_unbraced:Nf|
% \exp_last_unbraced:NV|
+% \exp_last_unbraced:No|
% \exp_last_unbraced:Nv|
% \exp_last_unbraced:NcV|
-% \exp_last_unbraced:NNo|
% \exp_last_unbraced:NNV|
+% \exp_last_unbraced:NNo|
+% \exp_last_unbraced:NNNV|
% \exp_last_unbraced:NNNo|
% }
% \begin{syntax}
@@ -1165,25 +1167,31 @@
%\end{macro}
%
%\begin{macro}{\exp_last_unbraced:NV}
+%\begin{macro}{\exp_last_unbraced:No}
%\begin{macro}{\exp_last_unbraced:Nv}
%\begin{macro}{\exp_last_unbraced:Nf}
%\begin{macro}{\exp_last_unbraced:NcV}
-%\begin{macro}{\exp_last_unbraced:NNo}
%\begin{macro}{\exp_last_unbraced:NNV}
+%\begin{macro}{\exp_last_unbraced:NNo}
+%\begin{macro}{\exp_last_unbraced:NNNV}
%\begin{macro}{\exp_last_unbraced:NNNo}
% Now the business end.
% \begin{macrocode}
\cs_new_nopar:Npn \exp_last_unbraced:Nf { \::f_unbraced \::: }
\cs_new_nopar:Npn \exp_last_unbraced:NV { \::V_unbraced \::: }
+\cs_new_nopar:Npn \exp_last_unbraced:No { \::o_unbraced \::: }
\cs_new_nopar:Npn \exp_last_unbraced:Nv { \::v_unbraced \::: }
\cs_new_nopar:Npn \exp_last_unbraced:NcV {
\::c \::V_unbraced \:::
}
+\cs_new_nopar:Npn \exp_last_unbraced:NNV {
+ \::N \::V_unbraced \:::
+}
\cs_new:Npn \exp_last_unbraced:NNo #1#2#3 {
\exp_after:wN #1 \exp_after:wN #2 #3
}
-\cs_new_nopar:Npn \exp_last_unbraced:NNV {
- \::N \::V_unbraced \:::
+\cs_new_nopar:Npn \exp_last_unbraced:NNNV {
+ \::N \::N \::V_unbraced \:::
}
\cs_new:Npn \exp_last_unbraced:NNNo #1#2#3#4 {
\exp_after:wN #1 \exp_after:wN #2 \exp_after:wN #3 #4
@@ -1196,6 +1204,8 @@
%\end{macro}
%\end{macro}
%\end{macro}
+%\end{macro}
+%\end{macro}
%
% \begin{macrocode}
%</initex|package>
diff --git a/Master/texmf-dist/source/latex/expl3/l3fp.dtx b/Master/texmf-dist/source/latex/expl3/l3fp.dtx
new file mode 100644
index 00000000000..7b3b63ba16f
--- /dev/null
+++ b/Master/texmf-dist/source/latex/expl3/l3fp.dtx
@@ -0,0 +1,2393 @@
+% \iffalse
+%% File: l3fp.dtx Copyright (C) 2010 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 ``expl3 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|package>
+\RequirePackage{l3names}
+%</driver|package>
+%\fi
+\GetIdInfo$Id: l3fp.dtx 1979 2010-07-08 19:51:19Z joseph $
+ {L3 Experimental floating-point operations}
+%\iffalse
+%<*driver>
+%\fi
+\ProvidesFile{\filename.\filenameext}
+ [\filedate\space v\fileversion\space\filedescription]
+%\iffalse
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{l3fp.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3fp} package\thanks{This file
+% has version number \fileversion, last
+% revised \filedate.}\\
+% Fixed-point arithmetic}
+% \author{\Team}
+% \date{\filedate}
+% \maketitle
+%
+%\begin{documentation}
+%
+%\section{Fixed-point numbers}
+%
+% This module implements a fixed-point data type and arithmetic support.
+% Fixed-point numbers are real numbers with a fixed range of decimal
+% places available, in this case nine before and nine after the
+% decimal point. As this is a low-level module, error-checking is
+% minimal.
+%
+% When parsing numbers, any missing parts will be interpreted as
+% zero. So for example
+%\begin{verbatim}
+% \fp_set:Nn \l_my_fp { }
+% \fp_set:Nn \l_my_fp { . }
+% \fp_set:Nn \l_my_fp { - }
+%\end{verbatim}
+% will all be interpreted as zero values without raising an error.
+%
+% Number which are too large for the fixed-point unit to handle will
+% result in errors, either from \TeX\ or from \LaTeX. The \LaTeX\ code
+% does not check that the input will not overflow, hence the
+% possibility of a \TeX\ error. On the other hand, numbers which are too
+% small will be dropped, which will mean that extra decimal digits will
+% simply be lost.
+%
+% Operations which give an undefined result (such as division by
+% \( 0 \)) or those which result in \( \pm \infty \) will not lead
+% to errors. Instead special marker values are returned, which
+% can be tested for using \cs{fp_if_undefined:N(TF)} and
+% \cs{fp_if_infinity:N(TF)}. In this way it is possible to work with
+% asymptopic functions without first checking the input. If these
+% special values are carried forward in calculations they will be
+% treated as \( 0 \).
+%
+% Fixed-point numbers are stored in the \texttt{fp} fixed-point
+% variable type. This has a standard range of functions for
+% variable management.
+%
+%\subsection{Fixed-point variables}
+%
+%\begin{function}{
+% \fp_new:N |
+% \fp_new:c |
+%}
+% \begin{syntax}
+% \cs{fp_new:N} \meta{fixed-point}
+% \end{syntax}
+% Creates a new \meta{fixed-point} or raises an error if the
+% name is already taken. The declaration global. The
+% \meta{fixed-point} will initially be set to "+0.000000000".
+%\end{function}
+%
+%\begin{function}{
+% \fp_set_eq:NN |
+% \fp_set_eq:cN |
+% \fp_set_eq:Nc |
+% \fp_set_eq:cc |
+%}
+% \begin{syntax}
+% \cs{fp_set_eq:NN} \meta{fp1} \meta{fp2}
+% \end{syntax}
+% Sets the value of \meta{fixed-point1} equal to that of
+% \meta{fixed-point2}. This assignment is restricted to the
+% current \TeX\ group level.
+%\end{function}
+%
+%\begin{function}{
+% \fp_gset_eq:NN |
+% \fp_gset_eq:cN |
+% \fp_gset_eq:Nc |
+% \fp_gset_eq:cc |
+%}
+% \begin{syntax}
+% \cs{tl_gset_eq:NN} \meta{tl var1} \meta{tl var2}
+% \end{syntax}
+% Sets the value of \meta{fixed-point1} equal to that of
+% \meta{fixed-point2}. This assignment is global and so is
+% not limited by the current \TeX\ group level.
+%\end{function}
+%
+%\begin{function}{
+% \fp_zero:N |
+% \fp_zero:c |
+%}
+% \begin{syntax}
+% \cs{fp_zero:N} \meta{fixed-point}
+% \end{syntax}
+% Sets the \meta{fixed-point} to "+0.000000000" within the current
+% scope.
+%\end{function}
+%
+%\begin{function}{
+% \fp_gzero:N |
+% \fp_gzero:c |
+%}
+% \begin{syntax}
+% \cs{fp_gzero:N} \meta{fixed-point}
+% \end{syntax}
+% Sets the \meta{fixed-point} to "+0.000000000" globally.
+%\end{function}
+%
+%\begin{function}{
+% \fp_set:Nn |
+% \fp_set:cn |
+%}
+% \begin{syntax}
+% \cs{fp_set:Nn} \meta{fixed-point} \Arg{value}
+% \end{syntax}
+% Sets the \meta{fixed-point} variable to \meta{value} within
+% the scope of the current \TeX\ group.
+%\end{function}
+%
+%\begin{function}{
+% \fp_gset:Nn |
+% \fp_gset:cn |
+%}
+% \begin{syntax}
+% \cs{fp_gset:Nn} \meta{fixed-point} \Arg{value}
+% \end{syntax}
+% Sets the \meta{fixed-point} variable to \meta{value} globally.
+%\end{function}
+%
+%\begin{function}{
+% \fp_set_from_dim:Nn |
+% \fp_set_from_dim:cn |
+%}
+% \begin{syntax}
+% \cs{fp_set_from_dim:Nn} \meta{fixed-point} \Arg{dimexpr}
+% \end{syntax}
+% Sets the \meta{fixed-point} variable to the distance represented
+% by the \meta{dimension expression} in the units points. This means
+% that distances given in other units are first converted to points
+% before being assigned to the \meta{fixed-point}. The assignment
+% is local.
+%\end{function}
+%
+%\begin{function}{
+% \fp_gset_from_dim:Nn |
+% \fp_gset_from_dim:cn |
+%}
+% \begin{syntax}
+% \cs{fp_gset_from_dim:Nn} \meta{fixed-point} \Arg{dimexpr}
+% \end{syntax}
+% Sets the \meta{fixed-point} variable to the distance represented
+% by the \meta{dimension expression} in the units points. This means
+% that distances given in other units are first converted to points
+% before being assigned to the \meta{fixed-point}. The assignment
+% is global.
+%\end{function}
+%
+%\begin{function}{
+% \fp_show:N |
+% \fp_show:c |
+%}
+% \begin{syntax}
+% \cs{fp_show:N} \meta{fixed-point}
+% \end{syntax}
+% Displays the content of the \meta{fixed-point} on the
+% terminal.
+%\end{function}
+%
+%\subsection{Unary operations}
+%
+% The unary operations alter the value stored within an \texttt{fp}
+% variable.
+%
+%\begin{function}{
+% \fp_abs:N |
+% \fp_abs:c |
+%}
+% \begin{syntax}
+% \cs{fp_abs:N} \meta{fixed-point}
+% \end{syntax}
+% Converts the \meta{fixed-point} to its absolute value, assigning
+% the result within the current \TeX\ group.
+%\end{function}
+%
+%\begin{function}{
+% \fp_gabs:N |
+% \fp_gabs:c |
+%}
+% \begin{syntax}
+% \cs{fp_gabs:N} \meta{fixed-point}
+% \end{syntax}
+% Converts the \meta{fixed-point} to its absolute value, assigning
+% the result globally.
+%\end{function}
+%
+%\begin{function}{
+% \fp_neg:N |
+% \fp_neg:c |
+%}
+% \begin{syntax}
+% \cs{fp_neg:N} \meta{fixed-point}
+% \end{syntax}
+% Reverse the sign of the \meta{fixed-point}, assigning the result
+% within the current \TeX\ group.
+%\end{function}
+%
+%\begin{function}{
+% \fp_gneg:N |
+% \fp_gneg:c |
+%}
+% \begin{syntax}
+% \cs{fp_gneg:N} \meta{fixed-point}
+% \end{syntax}
+% Reverse the sign of the \meta{fixed-point}, assigning the result
+% globally.
+%\end{function}
+%
+%\subsection{Transferring \texttt{fp} to \texttt{tl} data}
+%
+% The highly-structured internal format used for \texttt{fp} data
+% will not generally be desirable for use in user output. As a result,
+% the module provides a set of intermediate level functions to convert
+% \texttt{fp} into \texttt{tl} material. This process is governed by
+% a number of settings, which determine how the output is rounded and
+% how trailing zeros are handled.
+%
+%\begin{function}{
+% \fp_to_tl:NN |
+% \fp_to_tl:Nc |
+% \fp_to_tl:cN |
+% \fp_to_tl:cc |
+%}
+% \begin{syntax}
+% \cs{fp_to_tl:NN} \meta{fixed-point} \meta{token list variable}
+% \end{syntax}
+% Transfers the content of the \meta{fixed-point} into the
+% \meta{token list variable}, formatting according to the currently
+% prevailing formatting settings. The \meta{token list variable} is
+% set within the current \TeX\ group.
+%\end{function}
+%
+%\begin{function}{
+% \fp_gto_tl:NN |
+% \fp_gto_tl:Nc |
+% \fp_gto_tl:cN |
+% \fp_gto_tl:cc |
+%}
+% \begin{syntax}
+% \cs{fp_gto_tl:NN} \meta{fixed-point} \meta{token list variable}
+% \end{syntax}
+% Transfers the content of the \meta{fixed-point} into the
+% \meta{token list variable}, formatting according to the currently
+% prevailing formatting settings. The \meta{token list variable} is
+% set globally.
+%\end{function}
+%
+% The exact behaviour of the transfer process is governed by a small
+% family of key--value settings. These are accessible using the
+% \cs{keys_set:nn} function in the \texttt{fp} path:
+%\begin{verbatim}
+% \keys_set:nn { fp } {
+% % Settings here
+% }
+%\end{verbatim}
+%
+%\DescribeOption{remove-trailing-zeros}
+% The Boolean setting \texttt{remove-trailing-zeros} is used to govern
+% whether trailing zeros in the decimal part of the \texttt{fp} are
+% removed.
+%\begin{verbatim}
+% \fp_new:N \l_test_fp
+% \tl_new:N \l_test_tl
+% \fp_set:Nn \l_test_fp { 1.234 }
+% \keys_set:nn { fp } { remove-trailing-zeros = false }
+% \fp_to_tl \l_test_fp \l_test_tl % => '1.234000000'
+% \keys_set:nn { fp } { remove-trailing-zeros = true }
+% \fp_to_tl \l_test_fp \l_test_tl % => '1.234'
+%\end{verbatim}
+% Removing trailing zeros will always leave the result as a real number:
+%\begin{verbatim}
+% \fp_set:Nn \l_test_fp { 1.0 }
+% \keys_set:nn { fp } { remove-trailing-zeros = true }
+% \fp_to_tl \l_test_fp \l_test_tl % => '1.0'
+%\end{verbatim}
+%
+%\DescribeOption{round-mode}
+%\DescribeOption{precision}
+% The two options \texttt{round-mode} and \texttt{precision} determine
+% whether any rounding takes place for the decimal part of the output,
+% and if so how many significant output digits are retained. The
+% \texttt{precision} option indicates how many decimal digits should
+% be retained in the output, and therefore takes numerical values
+% only. The \texttt{round-mode} option takes one of the values
+% \texttt{none}, \texttt{truncate}, \texttt{half-from-zero} and
+% \texttt{half-even}. The \texttt{none} setting completely disables any
+% rounding, and therefore does not interact at all with
+% \texttt{precision}. The number of digits in the \texttt{tl} will
+% therefore depend only on the values in the \texttt{fp}, and whether
+% \texttt{remove-trailing-zeros} is active
+%\begin{verbatim}
+% \fp_set:Nn \l_test_fp { 1.234 }
+% \keys_set:nn { fp } {
+% round-mode = none ,
+% remove-trailing-zeros = false ,
+% }
+% \fp_to_tl \l_test_fp \l_test_tl % => '1.234000000'
+% \keys_set:nn { fp } {
+% round-mode = none ,
+% remove-trailing-zeros = true ,
+% }
+% \fp_to_tl \l_test_fp \l_test_tl % => '1.234'
+%\end{verbatim}
+% In all other cases (\texttt{truncate}, \texttt{half-from-zero}
+% and \texttt{half-even}) modification of the \texttt{fp} value will
+% always provide the number of decimal digits specified by
+% \texttt{precision}. This includes trailing zeros if they fall within
+% the \texttt{precision} requested. The \texttt{truncate} setting will
+% cause the transfer to simply discard excess decimal digits.
+%\begin{verbatim}
+% \keys_set:nn { fp } {
+% precision = 3 ,
+% remove-trailing-zeros = true ,
+% round-mode = truncate ,
+% }
+% \fp_set:Nn \l_test_fp { 1.23556 }
+% \fp_to_tl \l_test_fp \l_test_tl % => 1.235
+% \fp_set:Nn \l_test_fp { 1.2 }
+% \fp_to_tl \l_test_fp \l_test_tl % => 1.200
+%\end{verbatim}
+% The \texttt{half-from-zero} setting will round the number such that
+% if the digit to be rounded is \( 5 \) then rounding will occur
+% away from zero (increasing the absolute value).
+%\begin{verbatim}
+% \keys_set:nn { fp } {
+% precision = 3 ,
+% remove-trailing-zeros = true ,
+% round-mode = half-from-zero ,
+% }
+% \fp_set:Nn \l_test_fp { 1.23556 }
+% \fp_to_tl \l_test_fp \l_test_tl % => 1.236
+% \fp_set:Nn \l_test_fp { 1.2358 }
+% \fp_to_tl \l_test_fp \l_test_tl % => 1.236
+% \fp_set:Nn \l_test_fp { 1.23505 }
+% \fp_to_tl \l_test_fp \l_test_tl % => 1.235
+% \fp_set:Nn \l_test_fp { -1.23556 }
+% \fp_to_tl \l_test_fp \l_test_tl % => -1.236
+% \fp_set:Nn \l_test_fp { -1.23 }
+% \fp_to_tl \l_test_fp \l_test_tl % => -1.230
+%\end{verbatim}
+% The alternative \texttt{half-even} setting behaves indentically to
+% \texttt{half-from-zero} apart from the case where the discarded number
+% is exctly half. In this special case the result is rounded to the
+% nearest even number in the final digit. This form of rounding is
+% sometimes used as it is does not add any bias to the final result.
+%\begin{verbatim}
+% \keys_set:nn { fp } {
+% precision = 3 ,
+% remove-trailing-zeros = true ,
+% round-mode = half-even ,
+% }
+% \fp_set:Nn \l_test_fp { 1.23556 }
+% \fp_to_tl \l_test_fp \l_test_tl % => 1.236
+% \fp_set:Nn \l_test_fp { 1.23550 }
+% \fp_to_tl \l_test_fp \l_test_tl % => 1.236
+% \fp_set:Nn \l_test_fp { 1.23450 }
+% \fp_to_tl \l_test_fp \l_test_tl % => 1.234
+% \fp_set:Nn \l_test_fp { 1.234500001 }
+% \fp_to_tl \l_test_fp \l_test_tl % => 1.235
+%\end{verbatim}
+%
+%\subsection{Constants}
+%
+%\begin{variable}{ \c_zero_fp }
+% A permanently zero fixed-point variable.
+%\end{variable}
+%
+%\begin{variable}{ \c_undefined_fp }
+% A special marker fixed-point variable representing the result of
+% an operation which does not give a defined result (such as division
+% by \( 0 \)).
+%\end{variable}
+%
+%\begin{variable}{ \c_infinity_fp }
+% A special marker fixed-point variable representing \( \infty \).
+%\end{variable}
+%
+%\begin{variable}{ \c_minus_infinity_fp }
+% A special marker fixed-point variable representing \( -\infty \).
+%\end{variable}
+%
+%\subsection{Tests on fixed-point values}
+%
+%\begin{function}{
+% \fp_if_infinite_p:N / (EXP) |
+% \fp_if_infinite:N / (EXP) (TF) |
+%}
+% \begin{syntax}
+% \cs{fp_if_infinite_p:N} \meta{fixed-point}
+% \cs{fp_if_infinite:NTF} \meta{fixed-point}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if \meta{fixed-point} is infinite (\emph{i.e}.~equal to the
+% either of the special marker variables \cs{c_infinity_fp} or
+% \cs{c_minus_infinity_fp}). The branching versions then leave either
+% \meta{true code} or \meta{false code} in the input stream, as
+% appropriate to the truth of the test and the variant of the
+% function chosen. The logical truth of the test is left in the input
+% stream by the predicate version.
+%\end{function}
+%
+%\begin{function}{
+% \fp_if_plus_infinity_p:N / (EXP) |
+% \fp_if_plus_infinity:N / (EXP) (TF) |
+%}
+% \begin{syntax}
+% \cs{fp_if_plus_infinity_p:N} \meta{fixed-point}
+% \cs{fp_if_plus_infinity:NTF} \meta{fixed-point}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if \meta{fixed-point} is \( +\infty \) (\emph{i.e}.~equal to
+% the special \cs{c_infinity_fp} variable). The branching versions then
+% leave either \meta{true code} or \meta{false code} in the input
+% stream, as appropriate to the truth of the test and the variant of
+% the function chosen. The logical truth of the test is left in the
+% input stream by the predicate version.
+%\end{function}
+%
+%\begin{function}{
+% \fp_if_minus_infinity_p:N / (EXP) |
+% \fp_if_minus_infinity:N / (EXP) (TF) |
+%}
+% \begin{syntax}
+% \cs{fp_if_minus_infinity_p:N} \meta{fixed-point}
+% \cs{fp_if_minus_infinity:NTF} \meta{fixed-point}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if \meta{fixed-point} is \( +\infty \) (\emph{i.e}.~equal to
+% the special \cs{c_minus_infinity_fp} variable). The branching
+% versions then leave either \meta{true code} or \meta{false code} in
+% the input stream, as appropriate to the truth of the test and the
+% variant of the function chosen. The logical truth of the test is left
+% in the input stream by the predicate version.
+%\end{function}
+%
+%\begin{function}{
+% \fp_if_undefined_p:N / (EXP) |
+% \fp_if_undefined:N / (EXP) (TF) |
+%}
+% \begin{syntax}
+% \cs{fp_if_undefined_p:N} \meta{fixed-point}
+% \cs{fp_if_undefined:NTF} \meta{fixed-point}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if \meta{fixed-point} is undefined (\emph{i.e}.~equal to the
+% special \cs{c_undefined_fp} variable). The branching versions then
+% leave either \meta{true code} or \meta{false code} in the input
+% stream, as appropriate to the truth of the test and the variant of
+% the function chosen. The logical truth of the test is left in the
+% input stream by the predicate version.
+%\end{function}
+%
+%\begin{function}{
+% \fp_if_zero_p:N / (EXP) |
+% \fp_if_zero:N / (EXP) (TF) |
+%}
+% \begin{syntax}
+% \cs{fp_if_zero_p:N} \meta{fixed-point}
+% \cs{fp_if_zero:NTF} \meta{fixed-point} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if \meta{fixed-point} is equal to zero (\emph{i.e}.~equal to
+% the special \cs{c_zero_fp} variable). The branching versions then
+% leave either \meta{true code} or \meta{false code} in the input
+% stream, as appropriate to the truth of the test and the variant of
+% the function chosen. The logical truth of the test is left in the
+% input stream by the predicate version.
+%\end{function}
+%
+%\begin{function}{
+% \fp_compare:nNn / (TF) |
+% \fp_compare:NNN / (TF) |
+%}
+% \begin{syntax}
+% \cs{fp_compare:nNnTF} \Arg{value1} \meta{relation} \Arg{value2}
+% ~~\Arg{true code} \Arg{false code}
+% \cs{fp_compare:NNNTF} \Arg{fp1} \meta{relation} \Arg{fp2}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% Compares the two \meta{values} or \meta{fixed-points} based on the
+% \meta{relation} (\texttt{=}, \verb"<" or \verb">"), and leaves
+% either the \meta{true code} or \meta{false code} in the input stream,
+% as appropriate to the truth of the test and the variant of the
+% function chosen. The tests treat undefined fixed-points
+% as zero, as the comparison is intended for real numbers only.
+%\end{function}
+%
+%\subsection{Arithmetic operations}
+%
+% Binary arithmetic operations act on the value stored in an
+% \texttt{fp}, so for example
+%\begin{verbatim}
+% \fp_set:Nn \l_my_fp { 1.234 }
+% \fp_sub:Nn \l_my_fp { 5.678 }
+%\end{verbatim}
+% sets \cs{l_my_fp} to the result of \( 1.234 - 5.678 \)
+% (\emph{i.e}.~\( -4.444 \)).
+%
+%\begin{function}{
+% \fp_add:Nn |
+% \fp_add:cn |
+%}
+% \begin{syntax}
+% \cs{fp_add:Nn} \meta{fixed-point} \Arg{value}
+% \end{syntax}
+% Adds the \meta{value} to the \meta{fixed-point}, making the
+% assignment within the current \TeX\ group level.
+%\end{function}
+%
+%\begin{function}{
+% \fp_gadd:Nn |
+% \fp_gadd:cn |
+%}
+% \begin{syntax}
+% \cs{fp_gadd:Nn} \meta{fixed-point} \Arg{value}
+% \end{syntax}
+% Adds the \meta{value} to the \meta{fixed-point}, making the
+% assignment globally.
+%\end{function}
+%
+%\begin{function}{
+% \fp_sub:Nn |
+% \fp_sub:cn |
+%}
+% \begin{syntax}
+% \cs{fp_sub:Nn} \meta{fixed-point} \Arg{value}
+% \end{syntax}
+% Subtracts the \meta{value} from the \meta{fixed-point}, making the
+% assignment within the current \TeX\ group level.
+%\end{function}
+%
+%\begin{function}{
+% \fp_gsub:Nn |
+% \fp_gsub:cn |
+%}
+% \begin{syntax}
+% \cs{fp_gsub:Nn} \meta{fixed-point} \Arg{value}
+% \end{syntax}
+% Subtracts the \meta{value} from the \meta{fixed-point}, making the
+% assignment globally.
+%\end{function}
+%
+%\begin{function}{
+% \fp_mul:Nn |
+% \fp_mul:cn |
+%}
+% \begin{syntax}
+% \cs{fp_mul:Nn} \meta{fixed-point} \Arg{value}
+% \end{syntax}
+% Multiples the \meta{fixed-point} by the \meta{value}, making the
+% assignment within the current \TeX\ group level.
+%\end{function}
+%
+%\begin{function}{
+% \fp_gmul:Nn |
+% \fp_gmul:cn |
+%}
+% \begin{syntax}
+% \cs{fp_gmul:Nn} \meta{fixed-point} \Arg{value}
+% \end{syntax}
+% Multiples the \meta{fixed-point} by the \meta{value}, making the
+% assignment globally.
+%\end{function}
+%
+%\begin{function}{
+% \fp_div:Nn |
+% \fp_div:cn |
+%}
+% \begin{syntax}
+% \cs{fp_div:Nn} \meta{fixed-point} \Arg{value}
+% \end{syntax}
+% Divides the \meta{fixed-point} by the \meta{value}, making the
+% assignment within the current \TeX\ group level. If the \meta{value}
+% is zero, the \meta{fixed-point} will be set to \cs{c_undefined_fp}.
+%\end{function}
+%
+%\begin{function}{
+% \fp_gdiv:Nn |
+% \fp_gdiv:cn |
+%}
+% \begin{syntax}
+% \cs{fp_gdiv:Nn} \meta{fixed-point} \Arg{value}
+% \end{syntax}
+% Divides the \meta{fixed-point} by the \meta{value}, making the
+% assignment globally. If the \meta{value} is zero, the
+% \meta{fixed-point} will be set to \cs{c_undefined_fp}.
+%\end{function}
+%
+%\end{documentation}
+%
+%\begin{implementation}
+%
+%\section{Implementation}
+%
+% Announce and ensure that the required packages are loaded.
+% \begin{macrocode}
+%<*package>
+\ProvidesExplPackage
+ {\filename}{\filedate}{\fileversion}{\filedescription}
+\package_check_loaded_expl:
+%</package>
+%<*initex|package>
+% \end{macrocode}
+%
+% Internally, a fixed-point number is a token list variable of the
+% correct format. The first token in the variable is the sign: normally
+% this will be "+" or "-", but this token can also be used to indicate
+% a special state (for exampe if a calculation would give infinity as
+% a result). The main part of the number is then stored as a decimal:
+% there are always nine digits in the decimal part. This ensures that
+% two numbers which are equal to one another will always be stored in
+% the same way. For the same reason, zero is stored as "+0.000000000".
+%
+%\subsection{General variables}
+%
+%\begin{macro}{\l_fp_input_a_integer_int}
+%\begin{macro}{\l_fp_input_a_decimal_int}
+%\begin{macro}{\l_fp_input_b_integer_int}
+%\begin{macro}{\l_fp_input_b_decimal_int}
+% Storage for the input, divided into integer and decimal parts.
+% \begin{macrocode}
+\int_new:N \l_fp_input_a_integer_int
+\int_new:N \l_fp_input_a_decimal_int
+\int_new:N \l_fp_input_b_integer_int
+\int_new:N \l_fp_input_b_decimal_int
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_fp_input_a_sign_int}
+%\begin{macro}{\l_fp_input_b_sign_int}
+% The sign of each item in the input is stored as an \texttt{int} as
+% this allows some faster manipulation than would otherwise be possible.
+% \begin{macrocode}
+\int_new:N \l_fp_input_a_sign_int
+\int_new:N \l_fp_input_b_sign_int
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_fp_split_sign_int}
+% Used to speed up the sign-finding system.
+% \begin{macrocode}
+\int_new:N \l_fp_split_sign_int
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_fp_mul_a_i_int}
+%\begin{macro}{\l_fp_mul_a_ii_int}
+%\begin{macro}{\l_fp_mul_a_iii_int}
+%\begin{macro}{\l_fp_mul_a_iv_int}
+%\begin{macro}{\l_fp_mul_a_v_int}
+%\begin{macro}{\l_fp_mul_a_vi_int}
+%\begin{macro}{\l_fp_mul_b_i_int}
+%\begin{macro}{\l_fp_mul_b_ii_int}
+%\begin{macro}{\l_fp_mul_b_iii_int}
+%\begin{macro}{\l_fp_mul_b_iv_int}
+%\begin{macro}{\l_fp_mul_b_v_int}
+%\begin{macro}{\l_fp_mul_b_vi_int}
+% For multiplication, each number is split into six parts (three for the
+% decimal, three for the integer). So that they are a bt easier to keep
+% a track of these are simply numbered: i--iii are the integer and iv-vi
+% the decimal part.
+% \begin{macrocode}
+\int_new:N \l_fp_mul_a_i_int
+\int_new:N \l_fp_mul_a_ii_int
+\int_new:N \l_fp_mul_a_iii_int
+\int_new:N \l_fp_mul_a_iv_int
+\int_new:N \l_fp_mul_a_v_int
+\int_new:N \l_fp_mul_a_vi_int
+\int_new:N \l_fp_mul_b_i_int
+\int_new:N \l_fp_mul_b_ii_int
+\int_new:N \l_fp_mul_b_iii_int
+\int_new:N \l_fp_mul_b_iv_int
+\int_new:N \l_fp_mul_b_v_int
+\int_new:N \l_fp_mul_b_vi_int
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_fp_mul_output_int}
+%\begin{macro}{\l_fp_mul_output_tl}
+% Space for multiplication results.
+% \begin{macrocode}
+\int_new:N \l_fp_mul_output_int
+\tl_new:N \l_fp_mul_output_tl
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_fp_div_count_int}
+%\begin{macro}{\l_fp_div_offset_int}
+% Values used during division: an offset for small denominators and
+% a count for the actual division.
+% \begin{macrocode}
+\int_new:N \l_fp_div_count_int
+\int_new:N \l_fp_div_offset_int
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_fp_output_sign_int}
+%\begin{macro}{\l_fp_output_integer_int}
+%\begin{macro}{\l_fp_output_decimal_int}
+% Output is stored in the same way as input.
+% \begin{macrocode}
+\int_new:N \l_fp_output_sign_int
+\int_new:N \l_fp_output_integer_int
+\int_new:N \l_fp_output_decimal_int
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_fp_round_carry_bool}
+%\begin{macro}{\l_fp_round_decimal_tl}
+%\begin{macro}{\l_fp_round_discard_int}
+%\begin{macro}{\l_fp_round_position_int}
+% The rounding system needs space to track carrying forward and also
+% to hold onto dicarded material (which may be relevant when rounding
+% to an even last digit). The current position in the decimal part also
+% needs to be tracked. For speed reasons, the decimal part of the number
+% is build back up in a token list when rounding, as this avoids
+% worrying about place value.
+% \begin{macrocode}
+\bool_new:N \l_fp_round_carry_bool
+\tl_new:N \l_fp_round_decimal_tl
+\int_new:N \l_fp_round_discard_int
+\int_new:N \l_fp_round_position_int
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\l_fp_tmp_int}
+% A scratch \texttt{int}: used only where the value is not carried
+% forward.
+% \begin{macrocode}
+\int_new:N \l_fp_tmp_int
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\l_fp_tmp_tl}
+% The usual scratch token list.
+% \begin{macrocode}
+\tl_new:N \l_fp_tmp_tl
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Constants}
+%
+%\begin{macro}{\c_zero_fp}
+% The constanct zero value.
+% \begin{macrocode}
+\tl_new:N \c_zero_fp
+\tl_set:Nn \c_zero_fp { + 0.000000000 }
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\c_undefined_fp}
+%\begin{macro}{\c_infinity_fp}
+%\begin{macro}{\c_minus_infinity_fp}
+% Special marker values for various mathematically-valid results which
+% are not fixed-point numbers.
+% \begin{macrocode}
+\tl_new:N \c_undefined_fp
+\tl_set:Nn \c_undefined_fp { X 0.000000000 }
+\tl_new:N \c_infinity_fp
+\tl_set:Nn \c_infinity_fp { +2147483647.2147483647 }
+\tl_new:N \c_minus_infinity_fp
+\tl_set:Nn \c_minus_infinity_fp { -2147483647.2147483647 }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\c_one_hundred_million}
+%\begin{macro}{\c_one_thousand_million}
+% There is some speed to gain by moving numbers into fixed positions.
+% \begin{macrocode}
+\int_new:N \c_one_hundred_million
+\int_set:Nn \c_one_hundred_million { 100000000 }
+\int_new:N \c_one_thousand_million
+\int_set:Nn \c_one_thousand_million { 1000000000 }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{Tests for special values}
+%
+%\begin{macro}{\fp_if_infinite_p:N}
+%\begin{macro}[TF]{\fp_if_infinite:N}
+%\begin{macro}{\fp_if_plus_infinity_p:N}
+%\begin{macro}[TF]{\fp_if_plus_infinity:N}
+%\begin{macro}{\fp_if_minus_infinity_p:N}
+%\begin{macro}[TF]{\fp_if_minus_infinity:N}
+% Testing for infinite values is complicated by the sign of infinity.
+% There are therefore three tests, one which will match \( +\infty \)
+% or \( -\infty \) and one test each for the two individual cases.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \fp_if_infinite:N #1 { p , T , F , TF } {
+ \tex_ifx:D #1 \c_infinity_fp
+ \prg_return_true:
+ \tex_else:D
+ \tex_ifx:D #1 \c_minus_infinity_fp
+ \prg_return_true:
+ \tex_else:D
+ \prg_return_false:
+ \tex_fi:D
+ \tex_fi:D
+}
+\prg_new_conditional:Npnn \fp_if_plus_infinity:N #1 { p , T , F , TF } {
+ \tex_ifx:D #1 \c_infinity_fp
+ \prg_return_true:
+ \tex_else:D
+ \prg_return_false:
+ \tex_fi:D
+}
+\prg_new_conditional:Npnn \fp_if_minus_infinity:N #1 { p , T , F , TF }
+ {
+ \tex_ifx:D #1 \c_minus_infinity_fp
+ \prg_return_true:
+ \tex_else:D
+ \prg_return_false:
+ \tex_fi:D
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_if_undefined_p:N}
+%\begin{macro}[TF]{\fp_if_undefined:N}
+% Testing for an undefined value is easy.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \fp_if_undefined:N #1 { p , T , F , TF } {
+ \tex_ifx:D #1 \c_undefined_fp
+ \prg_return_true:
+ \tex_else:D
+ \prg_return_false:
+ \tex_fi:D
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_if_zero_p:N}
+%\begin{macro}[TF]{\fp_if_zero:N}
+% Testing for a zero fixed-point is also easy.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \fp_if_zero:N #1 { p , T , F , TF } {
+ \tex_ifx:D #1 \c_zero_fp
+ \prg_return_true:
+ \tex_else:D
+ \prg_return_false:
+ \tex_fi:D
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{Operations for \texttt{fp} variables}
+%
+%\begin{macro}{\fp_new:N}
+%\begin{macro}{\fp_new:c}
+% Fixed-points always have a value, and of course this has to be
+% initialised globally.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_new:N #1 {
+ \tl_new:N #1
+ \tl_gset_eq:NN #1 \c_zero_fp
+}
+\cs_generate_variant:Nn \fp_new:N { c }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_zero:N}
+%\begin{macro}{\fp_zero:c}
+%\begin{macro}{\fp_gzero:N}
+%\begin{macro}{\fp_gzero:c}
+% Zeroing fixed-points is pretty obvious.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_zero:N #1 {
+ \tl_set_eq:NN #1 \c_zero_fp
+}
+\cs_new_protected_nopar:Npn \fp_gzero:N #1 {
+ \tl_gset_eq:NN #1 \c_zero_fp
+}
+\cs_generate_variant:Nn \fp_zero:N { c }
+\cs_generate_variant:Nn \fp_gzero:N { c }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_set:Nn}
+%\begin{macro}{\fp_set:cn}
+%\begin{macro}{\fp_gset:Nn}
+%\begin{macro}{\fp_gset:cn}
+%\begin{macro}[aux]{\fp_set_aux:NNn}
+% To trap any input errors, a very simple version of the parser is run
+% here. This will pick up any invalid characters at this stage, saving
+% issues later. The splitting approach is the same as the more
+% advanced function later.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_set:Nn {
+ \fp_set_aux:NNn \tl_set:Nn
+}
+\cs_new_protected_nopar:Npn \fp_gset:Nn {
+ \fp_set_aux:NNn \tl_gset:Nn
+}
+\cs_new_protected_nopar:Npn \fp_set_aux:NNn #1#2#3 {
+ \group_begin:
+ \fp_split:Nn a {#3}
+ \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
+ \tl_set:Nx \l_fp_tmp_tl
+ {
+ \tex_ifnum:D \l_fp_input_a_sign_int < \c_zero
+ -
+ \tex_else:D
+ +
+ \tex_fi:D
+ \int_use:N \l_fp_input_a_integer_int
+ .
+ \exp_after:wN \use_none:n
+ \int_use:N \l_fp_input_a_decimal_int
+ }
+ \exp_after:wN \group_end: \exp_after:wN
+ #1 \exp_after:wN #2 \exp_after:wN { \l_fp_tmp_tl }
+}
+\cs_generate_variant:Nn \fp_set:Nn { c }
+\cs_generate_variant:Nn \fp_gset:Nn { c }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_set_from_dim:Nn}
+%\begin{macro}{\fp_set_from_dim:cn}
+%\begin{macro}{\fp_gset_from_dim:Nn}
+%\begin{macro}{\fp_gset_from_dim:cn}
+%\begin{macro}[aux]{\fp_set_from_dim_aux:NNn}
+%\begin{macro}[aux]{\fp_set_from_dim_aux:w}
+%\begin{macro}{\l_fp_tmp_dim}
+% Here, dimensions are converted to fixed-points \emph{via} a
+% temporary variable. This ensures that they always convert as points.
+% The code is then essentially the same as for \cs{fp_set:Nn}, but with
+% the dimension passed so that it will be striped of the "pt" on the
+% way through.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_set_from_dim:Nn {
+ \fp_set_from_dim_aux:NNn \tl_set:Nx
+}
+\cs_new_protected_nopar:Npn \fp_gset_from_dim:Nn {
+ \fp_set_from_dim_aux:NNn \tl_gset:Nx
+}
+\cs_new_protected_nopar:Npn \fp_set_from_dim_aux:NNn #1#2#3 {
+ \group_begin:
+ \l_fp_tmp_dim \etex_dimexpr:D #3 \scan_stop:
+ \fp_split:Nn a
+ {
+ \exp_after:wN \fp_set_from_dim_aux:w
+ \dim_use:N \l_fp_tmp_dim
+ }
+ \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
+ \tl_set:Nx \l_fp_tmp_tl
+ {
+ \tex_ifnum:D \l_fp_input_a_sign_int < \c_zero
+ -
+ \tex_else:D
+ +
+ \tex_fi:D
+ \int_use:N \l_fp_input_a_integer_int
+ .
+ \exp_after:wN \use_none:n
+ \int_use:N \l_fp_input_a_decimal_int
+ }
+ \exp_after:wN \group_end: \exp_after:wN
+ #1 \exp_after:wN #2 \exp_after:wN { \l_fp_tmp_tl }
+}
+\cs_set_protected_nopar:Npx \fp_set_from_dim_aux:w {
+ \cs_set_nopar:Npn \exp_not:N \fp_set_from_dim_aux:w
+ ##1 \tl_to_str:n { pt } {##1}
+}
+\fp_set_from_dim_aux:w
+\cs_generate_variant:Nn \fp_set_from_dim:Nn { c }
+\cs_generate_variant:Nn \fp_gset_from_dim:Nn { c }
+\dim_new:N \l_fp_tmp_dim
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_set_eq:NN}
+%\begin{macro}{\fp_set_eq:cN}
+%\begin{macro}{\fp_set_eq:Nc}
+%\begin{macro}{\fp_set_eq:cc}
+%\begin{macro}{\fp_gset_eq:NN}
+%\begin{macro}{\fp_gset_eq:cN}
+%\begin{macro}{\fp_gset_eq:Nc}
+%\begin{macro}{\fp_gset_eq:cc}
+% Pretty simple, really.
+% \begin{macrocode}
+\cs_new_eq:NN \fp_set_eq:NN \tl_set_eq:NN
+\cs_new_eq:NN \fp_set_eq:cN \tl_set_eq:cN
+\cs_new_eq:NN \fp_set_eq:Nc \tl_set_eq:Nc
+\cs_new_eq:NN \fp_set_eq:cc \tl_set_eq:cc
+\cs_new_eq:NN \fp_gset_eq:NN \tl_gset_eq:NN
+\cs_new_eq:NN \fp_gset_eq:cN \tl_gset_eq:cN
+\cs_new_eq:NN \fp_gset_eq:Nc \tl_gset_eq:Nc
+\cs_new_eq:NN \fp_gset_eq:cc \tl_gset_eq:cc
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_show:N}
+%\begin{macro}{\fp_show:c}
+% Simple showing of the underlying variable.
+% \begin{macrocode}
+\cs_new_eq:NN \fp_show:N \tl_show:N
+\cs_new_eq:NN \fp_show:c \tl_show:c
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_use:N}
+%\begin{macro}{\fp_use:c}
+% These are token lists, so this is easy.
+% \begin{macrocode}
+\cs_new_eq:NN \fp_use:N \tl_use:N
+\cs_new_eq:NN \fp_use:c \tl_use:c
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{Internal utilities}
+%
+%\begin{macro}{\fp_read:N}
+%\begin{macro}[aux]{\fp_read_aux:w}
+% Reading a stored value is made easier as the format is designed to
+% match the delimited function. This is always used to read the first
+% value (register "a").
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_read:N #1 {
+ \exp_after:wN \fp_read_aux:w #1 \q_stop
+}
+\cs_new_protected_nopar:Npn \fp_read_aux:w #1#2 . #3 \q_stop {
+ \tex_if:D #1 -
+ \l_fp_input_a_sign_int \c_minus_one
+ \tex_else:D
+ \l_fp_input_a_sign_int \c_one
+ \tex_fi:D
+ \l_fp_input_a_integer_int #2 \scan_stop:
+ \l_fp_input_a_decimal_int #3 \scan_stop:
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_split:Nn}
+%\begin{macro}[aux]{\fp_split_sign:}
+%\begin{macro}[aux]{\fp_split_aux_i:w}
+%\begin{macro}[aux]{\fp_split_aux_ii:w}
+%\begin{macro}[aux]{\fp_split_aux_iii:w}
+%\begin{macro}[aux]{\fp_split_decimal:w}
+%\begin{macro}[aux]{\fp_split_decimal_aux:w}
+% The aim here is to use as much of \TeX's mechanism as possible to pick
+% up the numerical input without any mistakes. In particular, negative
+% numbers have to be filtered out first in case the integer part is
+% \( 0 \) (in which case \TeX\ would drop the "-" sign). That process
+% has to be done in a loop for cases where the sign is repeated. The
+% next phase is to find the integer part, which will terminate
+% with a ".", and trigger the decimal-finding code. The later will
+% allow the decimal to be too long, truncating the result.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_split:Nn #1#2 {
+ \tl_set:Nx \l_fp_tmp_tl {#2}
+ \l_fp_split_sign_int \c_one
+ \fp_split_sign:
+ \use:c { l_fp_input_ #1 _sign_int } \l_fp_split_sign_int
+ \tex_afterassignment:D \fp_split_aux_i:w
+ \use:c { l_fp_input_ #1 _integer_int }
+ \etex_numexpr:D 0 \l_fp_tmp_tl . . \q_stop #1
+}
+\cs_new_protected_nopar:Npn \fp_split_sign: {
+ \tex_ifnum:D \pdf_strcmp:D
+ { \exp_after:wN \tl_head:w \l_fp_tmp_tl ? \q_nil } { - }
+ = \c_zero
+ \tl_set:Nx \l_fp_tmp_tl
+ {
+ \exp_after:wN
+ \tl_tail:w \l_fp_tmp_tl \prg_do_nothing: \q_nil
+ }
+ \l_fp_split_sign_int -\l_fp_split_sign_int
+ \exp_after:wN \fp_split_sign:
+ \tex_else:D
+ \tex_ifnum:D \pdf_strcmp:D
+ { \exp_after:wN \tl_head:w \l_fp_tmp_tl ? \q_nil } { + }
+ = \c_zero
+ \tl_set:Nx \l_fp_tmp_tl
+ {
+ \exp_after:wN
+ \tl_tail:w \l_fp_tmp_tl \prg_do_nothing: \q_nil
+ }
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \fp_split_sign:
+ \tex_fi:D
+ \tex_fi:D
+}
+\cs_new_protected_nopar:Npn \fp_split_aux_i:w #1 . #2 . #3 \q_stop {
+ \fp_split_aux_ii:w #2 000000000 \q_stop
+}
+\cs_new_protected_nopar:Npn \fp_split_aux_ii:w #1#2#3#4#5#6#7#8#9 {
+ \fp_split_aux_iii:w {#1#2#3#4#5#6#7#8#9}
+}
+\cs_new_protected_nopar:Npn \fp_split_aux_iii:w #1#2 \q_stop {
+ \l_fp_tmp_int 1 #1 \scan_stop:
+ \exp_after:wN \fp_split_decimal:w
+ \int_use:N \l_fp_tmp_int 000000000 \q_stop
+}
+\cs_new_protected_nopar:Npn \fp_split_decimal:w #1#2#3#4#5#6#7#8#9 {
+ \fp_split_decimal_aux:w {#2#3#4#5#6#7#8#9}
+}
+\cs_new_protected_nopar:Npn \fp_split_decimal_aux:w #1#2#3 \q_stop #4 {
+ \use:c { l_fp_input_ #4 _decimal_int } #1#2 \scan_stop:
+ \tex_ifnum:D
+ \etex_numexpr:D
+ \use:c { l_fp_input_ #4 _integer_int } +
+ \use:c { l_fp_input_ #4 _decimal_int }
+ \scan_stop:
+ = \c_zero
+ \use:c { l_fp_input_ #4 _sign_int } \c_one
+ \tex_fi:D
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{Unary functions}
+%
+%\begin{macro}{\fp_abs:N}
+%\begin{macro}{\fp_abs:c}
+%\begin{macro}{\fp_gabs:N}
+%\begin{macro}{\fp_gabs:c}
+%\begin{macro}[aux]{\fp_abs_aux:NN}
+% Setting the absolute value is easy: read the value, ignore the sign,
+% return the result.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_abs:N {
+ \fp_abs:NN \tl_set:Nn
+}
+\cs_new_protected_nopar:Npn \fp_gabs:N {
+ \fp_abs:NN \tl_gset:Nn
+}
+\cs_generate_variant:Nn \fp_abs:N { c }
+\cs_generate_variant:Nn \fp_gabs:N { c }
+\cs_new_protected_nopar:Npn \fp_abs:NN #1#2 {
+ \group_begin:
+ \fp_read:N #2
+ \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
+ \tl_set:Nx \l_fp_tmp_tl
+ {
+ +
+ \int_use:N \l_fp_input_a_integer_int
+ .
+ \exp_after:wN \use_none:n
+ \int_use:N \l_fp_input_a_decimal_int
+ }
+ \exp_after:wN \group_end: \exp_after:wN
+ #1 \exp_after:wN #2 \exp_after:wN { \l_fp_tmp_tl }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_neg:N}
+%\begin{macro}{\fp_neg:c}
+%\begin{macro}{\fp_gneg:N}
+%\begin{macro}{\fp_gneg:c}
+%\begin{macro}[aux]{\fp_neg:NN}
+% Just a bit more complex: read the input, reverse the sign and
+% output the result.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_neg:N {
+ \fp_neg_aux:NN \tl_set:Nn
+}
+\cs_new_protected_nopar:Npn \fp_gneg:N {
+ \fp_neg_aux:NN \tl_gset:Nn
+}
+\cs_generate_variant:Nn \fp_neg:N { c }
+\cs_generate_variant:Nn \fp_gneg:N { c }
+\cs_new_protected_nopar:Npn \fp_neg_aux:NN #1#2 {
+ \group_begin:
+ \fp_read:N #2
+ \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
+ \tl_set:Nx \l_fp_tmp_tl
+ {
+ \tex_ifnum:D \l_fp_input_a_sign_int < \c_zero
+ +
+ \tex_else:D
+ -
+ \tex_fi:D
+ \int_use:N \l_fp_input_a_integer_int
+ .
+ \exp_after:wN \use_none:n
+ \int_use:N \l_fp_input_a_decimal_int
+ }
+ \exp_after:wN \group_end: \exp_after:wN
+ #1 \exp_after:wN #2 \exp_after:wN { \l_fp_tmp_tl }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{Basic arithmetic}
+%
+%\begin{macro}{\fp_add:Nn}
+%\begin{macro}{\fp_add:cn}
+%\begin{macro}{\fp_gadd:Nn}
+%\begin{macro}{\fp_gadd:cn}
+%\begin{macro}[aux]{\fp_add_aux:NNn}
+%\begin{macro}[aux]{\fp_add_core:}
+% The various addition functions are simply different ways to call the
+% single master function below. This pattern is repeated for the
+% other arithmetic functions.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_add:Nn {
+ \fp_add_aux:NNn \tl_set:Nn
+}
+\cs_new_protected_nopar:Npn \fp_gadd:Nn {
+ \fp_add_aux:NNn \tl_gset:Nn
+}
+\cs_generate_variant:Nn \fp_add:Nn { c }
+\cs_generate_variant:Nn \fp_gadd:Nn { c }
+% \end{macrocode}
+% Addition takes place using one of two paths. If the signs of the
+% two parts are the same, they are simply combined. On the other
+% hand, if the signs are different the calculation finds this
+% difference.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_add_aux:NNn #1#2#3 {
+ \group_begin:
+ \fp_read:N #2
+ \fp_split:Nn b {#3}
+ \fp_add_core:
+ \exp_after:wN \group_end: \exp_after:wN
+ #1 \exp_after:wN #2 \exp_after:wN { \l_fp_tmp_tl }
+}
+\cs_new_protected_nopar:Npn \fp_add_core: {
+ \tex_ifnum:D
+ \etex_numexpr:D
+ \l_fp_input_a_sign_int * \l_fp_input_b_sign_int
+ \scan_stop:
+ > \c_zero
+ \exp_after:wN \fp_add_sum:
+ \tex_else:D
+ \exp_after:wN \fp_add_difference:
+ \tex_fi:D
+ \tl_set:Nx \l_fp_tmp_tl
+ {
+ \tex_ifnum:D \l_fp_output_sign_int < \c_zero
+ -
+ \tex_else:D
+ +
+ \tex_fi:D
+ \int_use:N \l_fp_output_integer_int
+ .
+ \exp_after:wN \use_none:n
+ \int_use:N \l_fp_output_decimal_int
+ }
+}
+% \end{macrocode}
+% Finding the sum of two numbers is trivially easy.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_add_sum: {
+ \l_fp_output_sign_int \l_fp_input_a_sign_int
+ \l_fp_output_integer_int
+ \etex_numexpr:D
+ \l_fp_input_a_integer_int + \l_fp_input_b_integer_int
+ \scan_stop:
+ \l_fp_output_decimal_int
+ \etex_numexpr:D
+ \l_fp_input_a_decimal_int + \l_fp_input_b_decimal_int
+ \scan_stop:
+ \tex_ifnum:D \l_fp_output_decimal_int < \c_one_thousand_million
+ \tex_advance:D \l_fp_output_decimal_int \c_one_thousand_million
+ \tex_else:D
+ \tex_advance:D \l_fp_output_integer_int \c_one
+ \tex_fi:D
+}
+% \end{macrocode}
+% When the signs of the two parts of the input are different, the
+% absolute difference is worked out first. There is then a caculation to
+% see which way around everything has worked out, so that the final
+% sign is correct. The differnce might also give a zero resul with
+% a negative sign, which is reversed as zero is regarded as positive.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_add_difference: {
+ \l_fp_output_integer_int
+ \etex_numexpr:D
+ \l_fp_input_a_integer_int - \l_fp_input_b_integer_int
+ \scan_stop:
+ \l_fp_output_decimal_int
+ \etex_numexpr:D
+ \l_fp_input_a_decimal_int - \l_fp_input_b_decimal_int
+ \scan_stop:
+ \tex_ifnum:D \l_fp_output_decimal_int < \c_zero
+ \tex_advance:D \l_fp_output_integer_int \c_minus_one
+ \tex_advance:D \l_fp_output_decimal_int \c_one_thousand_million
+ \tex_fi:D
+ \tex_ifnum:D \l_fp_output_integer_int < \c_zero
+ \l_fp_output_sign_int \l_fp_input_b_sign_int
+ \tex_ifnum:D \l_fp_output_decimal_int = \c_zero
+ \l_fp_output_integer_int -\l_fp_output_integer_int
+ \tex_else:D
+ \l_fp_output_decimal_int
+ \etex_numexpr:D
+ \c_one_thousand_million - \l_fp_output_decimal_int
+ \scan_stop:
+ \l_fp_output_integer_int
+ \etex_numexpr:D
+ - \l_fp_output_integer_int - \c_one
+ \scan_stop:
+ \tex_fi:D
+ \tex_else:D
+ \l_fp_output_sign_int \l_fp_input_a_sign_int
+ \tex_fi:D
+ \tex_ifnum:D
+ \etex_numexpr:D
+ \l_fp_output_integer_int + \l_fp_output_decimal_int
+ \scan_stop:
+ = \c_zero
+ \l_fp_output_sign_int \c_one
+ \tex_fi:D
+ \tex_advance:D \l_fp_output_decimal_int \c_one_thousand_million
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_sub:Nn}
+%\begin{macro}{\fp_sub:cn}
+%\begin{macro}{\fp_gsub:Nn}
+%\begin{macro}{\fp_gsub:cn}
+%\begin{macro}[aux]{\fp_sub_aux:NNn}
+% Subtraction is essentially the same as addition, but with the sign
+% of the second component reversed. Thus the core of the two function
+% groups is the same, with just a little set up here.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_sub:Nn {
+ \fp_sub_aux:NNn \tl_set:Nn
+}
+\cs_new_protected_nopar:Npn \fp_gsub:Nn {
+ \fp_sub_aux:NNn \tl_gset:Nn
+}
+\cs_generate_variant:Nn \fp_sub:Nn { c }
+\cs_generate_variant:Nn \fp_gsub:Nn { c }
+\cs_new_protected_nopar:Npn \fp_sub_aux:NNn #1#2#3 {
+ \group_begin:
+ \fp_read:N #2
+ \fp_split:Nn b {#3}
+ \tex_multiply:D \l_fp_input_b_sign_int \c_minus_one
+ \fp_add_core:
+ \exp_after:wN \group_end: \exp_after:wN
+ #1 \exp_after:wN #2 \exp_after:wN { \l_fp_tmp_tl }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_mul:Nn}
+%\begin{macro}{\fp_mul:cn}
+%\begin{macro}{\fp_gmul:Nn}
+%\begin{macro}{\fp_gmul:cn}
+%\begin{macro}[aux]{\fp_mul_aux:NNn}
+%\begin{macro}[aux]{\fp_mul_split:NNNN}
+%\begin{macro}[aux]{\fp_mul_split:w}
+%\begin{macro}[aux]{\fp_mul_end_level:}
+%\begin{macro}[aux]{\fp_mul_end_level:w}
+% The pattern is much the same for multiplication.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_mul:Nn {
+ \fp_mul_aux:NNn \tl_set:Nn
+}
+\cs_new_protected_nopar:Npn \fp_gmul:Nn {
+ \fp_mul_aux:NNn \tl_gset:Nn
+}
+\cs_generate_variant:Nn \fp_mul:Nn { c }
+\cs_generate_variant:Nn \fp_gmul:Nn { c }
+% \end{macrocode}
+% The approach to multiplication is as follows. First, the two numbers
+% are split into blocks of three digits. These are then multiplied
+% together to find products for each group of three output digits. This
+% is al written out in full for speed reasons. Between each block of
+% three digits in the output, there is a carry step. The very lowest
+% digits are not calculated, while
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_mul_aux:NNn #1#2#3 {
+ \group_begin:
+ \fp_read:N #2
+ \fp_split:Nn b {#3}
+ \fp_mul_split:NNNN \l_fp_input_a_integer_int
+ \l_fp_mul_a_i_int \l_fp_mul_a_ii_int \l_fp_mul_a_iii_int
+ \fp_mul_split:NNNN \l_fp_input_a_decimal_int
+ \l_fp_mul_a_iv_int \l_fp_mul_a_v_int \l_fp_mul_a_vi_int
+ \fp_mul_split:NNNN \l_fp_input_b_integer_int
+ \l_fp_mul_b_i_int \l_fp_mul_b_ii_int \l_fp_mul_b_iii_int
+ \fp_mul_split:NNNN \l_fp_input_b_decimal_int
+ \l_fp_mul_b_iv_int \l_fp_mul_b_v_int \l_fp_mul_b_vi_int
+ \l_fp_mul_output_int \c_zero
+ \tl_clear:N \l_fp_mul_output_tl
+ \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_vi_int
+ \fp_mul_product:NN \l_fp_mul_a_v_int \l_fp_mul_b_v_int
+ \fp_mul_product:NN \l_fp_mul_a_vi_int \l_fp_mul_b_iv_int
+ \tex_divide:D \l_fp_mul_output_int \c_thousand
+ \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_vi_int
+ \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_v_int
+ \fp_mul_product:NN \l_fp_mul_a_v_int \l_fp_mul_b_iv_int
+ \fp_mul_product:NN \l_fp_mul_a_vi_int \l_fp_mul_b_iii_int
+ \fp_mul_end_level:
+ \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_vi_int
+ \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_v_int
+ \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_iv_int
+ \fp_mul_product:NN \l_fp_mul_a_v_int \l_fp_mul_b_iii_int
+ \fp_mul_product:NN \l_fp_mul_a_vi_int \l_fp_mul_b_ii_int
+ \fp_mul_end_level:
+ \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_vi_int
+ \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_v_int
+ \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_iv_int
+ \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_iii_int
+ \fp_mul_product:NN \l_fp_mul_a_v_int \l_fp_mul_b_ii_int
+ \fp_mul_product:NN \l_fp_mul_a_vi_int \l_fp_mul_b_i_int
+ \fp_mul_end_level:
+ \l_fp_output_decimal_int 0 \l_fp_mul_output_tl \scan_stop:
+ \tl_clear:N \l_fp_mul_output_tl
+ \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_v_int
+ \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_iv_int
+ \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_iii_int
+ \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_ii_int
+ \fp_mul_product:NN \l_fp_mul_a_v_int \l_fp_mul_b_i_int
+ \fp_mul_end_level:
+ \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_iv_int
+ \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_iii_int
+ \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_ii_int
+ \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_i_int
+ \fp_mul_end_level:
+ \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_iii_int
+ \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_ii_int
+ \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_i_int
+ \fp_mul_end_level:
+ \l_fp_output_integer_int 0 \l_fp_mul_output_tl \scan_stop:
+ \tl_clear:N \l_fp_mul_output_tl
+ \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_ii_int
+ \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_i_int
+ \fp_mul_end_level:
+ \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_i_int
+ \fp_mul_end_level:
+ \tex_ifnum:D \l_fp_mul_output_tl = \c_zero
+ \tex_else:D
+ \exp_after:wN \fp_msg_overflow:
+ \tex_fi:D
+ \tex_advance:D \l_fp_output_decimal_int \c_one_thousand_million
+ \tl_set:Nx \l_fp_tmp_tl
+ {
+ \tex_ifnum:D
+ \etex_numexpr:D
+ \l_fp_input_a_sign_int * \l_fp_input_b_sign_int
+ \scan_stop:
+ < \c_zero
+ \tex_ifnum:D
+ \etex_numexpr:D
+ \l_fp_output_integer_int + \l_fp_output_decimal_int
+ \scan_stop:
+ = \c_one_thousand_million
+ +
+ \tex_else:D
+ -
+ \tex_fi:D
+ \tex_else:D
+ +
+ \tex_fi:D
+ \int_use:N \l_fp_output_integer_int
+ .
+ \exp_after:wN \use_none:n
+ \int_use:N \l_fp_output_decimal_int
+ }
+ \exp_after:wN \group_end: \exp_after:wN
+ #1 \exp_after:wN #2 \exp_after:wN { \l_fp_tmp_tl }
+}
+% \end{macrocode}
+% The split works by making a \( 10 \) digit number, from which
+% the first digit can then be dropped using a delimited argument. The
+% groups of three digits are then assigned to the various parts of
+% the input: notice that "##9" contains the last two digits of the
+% smallest part of the input.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_mul_split:NNNN #1#2#3#4 {
+ \tex_advance:D #1 \c_one_thousand_million
+ \cs_set_protected_nopar:Npn \fp_mul_split_aux:w
+ ##1##2##3##4##5##6##7##8##9 \q_stop {
+ #2 ##2##3##4 \scan_stop:
+ #3 ##5##6##7 \scan_stop:
+ #4 ##8##9 \scan_stop:
+ }
+ \exp_after:wN \fp_mul_split_aux:w \int_use:N #1 \q_stop
+}
+\cs_new_protected_nopar:Npn \fp_mul_product:NN #1#2 {
+ \l_fp_mul_output_int
+ \etex_numexpr:D \l_fp_mul_output_int + #1 * #2 \scan_stop:
+}
+% \end{macrocode}
+% At the end of each output group of three, there is a transfer of
+% information so that there is no danger of an overflow. This is done by
+% expansion to keep the number of calculations down.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_mul_end_level: {
+ \tex_advance:D \l_fp_mul_output_int \c_one_thousand_million
+ \exp_after:wN \fp_mul_end_level:w
+ \int_use:N \l_fp_mul_output_int \q_stop
+}
+\cs_new_protected_nopar:Npn \fp_mul_end_level:w
+ #1#2#3#4#5#6#7#8#9 \q_stop {
+ \tl_set:Nx \l_fp_mul_output_tl { #8#9 \l_fp_mul_output_tl }
+ \l_fp_mul_output_int #5#6#7 \scan_stop:
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_div:Nn}
+%\begin{macro}{\fp_div:cn}
+%\begin{macro}{\fp_gdiv:Nn}
+%\begin{macro}{\fp_gdiv:cn}
+%\begin{macro}[aux]{\fp_div_aux:NNn}
+%\begin{macro}[aux]{\fp_div_aux:}
+%\begin{macro}[aux]{\fp_div_offset_create:}
+%\begin{macro}[aux]{\fp_div_offset_create_aux:w}
+%\begin{macro}[aux]{\fp_div_loop:}
+%\begin{macro}[aux]{\fp_div_loop_aux_i:w}
+%\begin{macro}[aux]{\fp_div_loop_aux_ii:w}
+%\begin{macro}[aux]{\fp_div_divide:}
+%\begin{macro}[aux]{\fp_div_divide_aux:}
+%\begin{macro}[aux]{\fp_div_store:}
+%\begin{macro}[aux]{\fp_div_store_integer:}
+%\begin{macro}[aux]{\fp_div_store_decimal:}
+% The pattern is much the same for multiplication.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_div:Nn {
+ \fp_div_aux:NNn \tl_set:Nn
+}
+\cs_new_protected_nopar:Npn \fp_gdiv:Nn {
+ \fp_div_aux:NNn \tl_gset:Nn
+}
+\cs_generate_variant:Nn \fp_div:Nn { c }
+\cs_generate_variant:Nn \fp_gdiv:Nn { c }
+
+% \end{macrocode}
+% Division proper starts with a couple of tests. If the denominator is
+% zero then a error is issued. On the other hand, if the numerator is
+% zero then the result must be \( 0.0 \) and can be given with no
+% further work.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_div_aux:NNn #1#2#3 {
+ \group_begin:
+ \fp_read:N #2
+ \fp_split:Nn b {#3}
+ \tex_ifnum:D
+ \etex_numexpr:D
+ \l_fp_input_b_integer_int + \l_fp_input_b_decimal_int
+ \scan_stop:
+ = \c_zero
+ \tl_set_eq:NN \l_fp_tmp_tl \c_undefined_fp
+ \tex_else:D
+ \tex_ifnum:D
+ \etex_numexpr:D
+ \l_fp_input_a_integer_int + \l_fp_input_a_decimal_int
+ \scan_stop:
+ = \c_zero
+ \tl_set_eq:NN \l_fp_tmp_tl \c_zero_fp
+ \tex_else:D
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \fp_div_aux:
+ \tex_fi:D
+ \tex_fi:D
+ \exp_after:wN \group_end: \exp_after:wN
+ #1 \exp_after:wN #2 \exp_after:wN { \l_fp_tmp_tl }
+}
+% \end{macrocode}
+% The main division algorithm has to avoid overflows for awkward
+% cases (division of large numbers by small ones). That requires that
+% the denominator has an integer part if the numerator does: an offset
+% is only created if it is needed. The idea then is find how many
+% times the denominator can be removed from the numerator. This
+% is stored in the result, the denominator is divided by ten and
+% the process is repeated with the remainder of the numerator. Cycling
+% through this sequence eventually removes all of the digits of the
+% denominator, if the numerator does not reach zero first.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_div_aux: {
+ \l_fp_div_offset_int \c_one
+ \tex_ifnum:D \l_fp_input_a_integer_int > \c_zero
+ \exp_after:wN \fp_div_offset_create:
+ \tex_fi:D
+ \l_fp_output_integer_int \c_zero
+ \l_fp_output_decimal_int \c_one_thousand_million
+ \cs_set_eq:NN \fp_div_store: \fp_div_store_integer:
+ \fp_div_loop:
+ \tl_set:Nx \l_fp_tmp_tl
+ {
+ \tex_ifnum:D
+ \etex_numexpr:D
+ \l_fp_input_a_sign_int * \l_fp_input_b_sign_int
+ \scan_stop:
+ < \c_zero
+ \tex_ifnum:D
+ \etex_numexpr:D
+ \l_fp_output_integer_int + \l_fp_output_decimal_int
+ \scan_stop:
+ = \c_one_thousand_million
+ +
+ \tex_else:D
+ -
+ \tex_fi:D
+ \tex_else:D
+ +
+ \tex_fi:D
+ \int_use:N \l_fp_output_integer_int
+ .
+ \exp_after:wN \use_none:n
+ \int_use:N \l_fp_output_decimal_int
+ }
+}
+% \end{macrocode}
+% The offset is created such that it will automatically be accounted
+% for in the rest of the process. Rather than doing any integer division
+% a delimited function is used to transfer the digit from the
+% integer to the decimal parts.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_div_offset_create: {
+ \tex_ifnum:D \l_fp_input_b_integer_int = \c_zero
+ \tex_advance:D \l_fp_input_b_decimal_int \c_one_thousand_million
+ \exp_after:wN \fp_div_offset_create_aux:w
+ \int_use:N \l_fp_input_b_decimal_int \q_stop
+ \exp_after:wN \fp_div_offset_create:
+ \tex_fi:D
+}
+\cs_new_protected_nopar:Npn \fp_div_offset_create_aux:w
+ #1#2#3#4#5#6#7#8#9 \q_stop {
+ \l_fp_input_b_integer_int #2 \scan_stop:
+ \l_fp_input_b_decimal_int #3#4#5#6#7#8#9 0 \scan_stop:
+ \tex_multiply:D \l_fp_div_offset_int \c_ten
+}
+% \end{macrocode}
+% The main division loop must start with both numerator and
+% denominator above zero, so the test is at the tail of the loop.
+% Once again, division by ten for the denominator is avoided, with
+% a delimited function doing the job. The test at the end of the
+% function means that the loop terminates as soon as one part of the
+% input reaches zero: this saves dead loops if the division is
+% exact.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_div_loop: {
+ \l_fp_div_count_int \c_zero
+ \fp_div_divide:
+ \tex_divide:D \l_fp_input_b_decimal_int \c_ten
+ \tex_advance:D \l_fp_input_b_integer_int \c_one_thousand_million
+ \exp_after:wN \fp_div_loop_aux_i:w
+ \int_use:N \l_fp_input_b_integer_int
+ \fp_div_store:
+ \tex_ifnum:D
+ \etex_numexpr:D
+ \l_fp_input_a_integer_int + \l_fp_input_a_decimal_int
+ > \c_zero
+ \tex_ifnum:D
+ \etex_numexpr:D
+ \l_fp_input_b_integer_int + \l_fp_input_b_decimal_int
+ > \c_zero
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \fp_div_loop:
+ \tex_fi:D
+ \tex_fi:D
+}
+% \end{macrocode}
+% Checking to see if the numerator can be divides needs quite an
+% involved check. Either the integer part has to be bigger for the
+% numerator or, if it is not smaller then the decimal part of the
+% numerator must not be smaller than that of the denominator. Once
+% the test is right the rest is much as elsewhere.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_div_divide: {
+ \tex_ifnum:D \l_fp_input_a_integer_int > \l_fp_input_b_integer_int
+ \exp_after:wN \fp_div_divide_aux:
+ \tex_else:D
+ \tex_ifnum:D \l_fp_input_a_integer_int < \l_fp_input_b_integer_int
+ \tex_else:D
+ \tex_ifnum:D
+ \l_fp_input_a_decimal_int < \l_fp_input_b_decimal_int
+ \tex_else:D
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_after:wN \fp_div_divide_aux:
+ \tex_fi:D
+ \tex_fi:D
+ \tex_fi:D
+}
+\cs_new_protected_nopar:Npn \fp_div_loop_aux_i:w #1#2#3#4#5#6#7#8#9 {
+ \fp_div_loop_aux_ii:w #2#3#4#5#6#7#8#9
+}
+\cs_new_protected_nopar:Npn \fp_div_loop_aux_ii:w #1#2#3#4#5#6#7#8#9 {
+ \l_fp_input_b_integer_int #1#2#3#4#5#6#7#8 \scan_stop:
+ \l_fp_input_b_decimal_int
+ \etex_numexpr:D
+ \l_fp_input_b_decimal_int + \c_one_hundred_million * #9
+ \scan_stop:
+}
+\cs_new_protected_nopar:Npn \fp_div_divide_aux: {
+ \tex_advance:D \l_fp_div_count_int \c_one
+ \tex_advance:D \l_fp_input_a_integer_int -\l_fp_input_b_integer_int
+ \tex_advance:D \l_fp_input_a_decimal_int -\l_fp_input_b_decimal_int
+ \tex_ifnum:D \l_fp_input_a_decimal_int < \c_zero
+ \tex_advance:D \l_fp_input_a_integer_int \c_minus_one
+ \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
+ \tex_fi:D
+ \fp_div_divide:
+}
+% \end{macrocode}
+% The final stage of each loop is to store the result. This is done
+% separately for the integer and decimal parts. The offset is used to
+% get the digits in the correct place, and so also indicates when the
+% switch from the integer to the decimal.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_div_store: { }
+\cs_new_protected_nopar:Npn \fp_div_store_integer: {
+ \l_fp_output_integer_int
+ \etex_numexpr:D
+ \l_fp_output_integer_int +
+ \l_fp_div_count_int * \l_fp_div_offset_int
+ \scan_stop:
+ \tex_ifnum:D \l_fp_div_offset_int > \c_one
+ \tex_divide:D \l_fp_div_offset_int \c_ten
+ \tex_else:D
+ \cs_set_eq:NN \fp_div_store: \fp_div_store_decimal:
+ \l_fp_div_offset_int \c_one_hundred_million
+ \tex_fi:D
+}
+\cs_new_protected_nopar:Npn \fp_div_store_decimal: {
+ \l_fp_output_decimal_int
+ \etex_numexpr:D
+ \l_fp_output_decimal_int +
+ \l_fp_div_count_int * \l_fp_div_offset_int
+ \scan_stop:
+ \tex_divide:D \l_fp_div_offset_int \c_ten
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{Fixed-point conditionals}
+%
+%\begin{macro}[TF]{\fp_compare:nNn}
+%\begin{macro}[TF]{\fp_compare:NNN}
+%\begin{macro}[aux]{\fp_compare_aux:N}
+%\begin{macro}[aux]{\fp_compare_=:}
+%\begin{macro}[aux]{\fp_compare_<:}
+%\begin{macro}[aux]{\fp_compare_>:}
+%\begin{macro}[aux]{\fp_compare_absolute_a>b:}
+%\begin{macro}[aux]{\fp_compare_absolute_a<b:}
+% The idea for the comparisons is to provide two versions: slower and
+% faster. The lead off for both is the same: get the two numbers
+% read and then look for a function to handle the comparison.
+% \begin{macrocode}
+\prg_new_protected_conditional:Npnn \fp_compare:nNn #1#2#3
+ { T , F , TF } {
+ \group_begin:
+ \fp_split:Nn a {#1}
+ \fp_split:Nn b {#3}
+ \fp_compare_aux:N #2
+}
+\prg_new_protected_conditional:Npnn \fp_compare:NNN #1#2#3
+ { T , F , TF } {
+ \group_begin:
+ \fp_read:N #3
+ \l_fp_input_b_sign_int \l_fp_input_a_sign_int
+ \l_fp_input_b_integer_int \l_fp_input_a_integer_int
+ \l_fp_input_b_decimal_int \l_fp_input_a_decimal_int
+ \fp_read:N #1
+ \fp_compare_aux:N #2
+}
+\cs_new_protected_nopar:Npn \fp_compare_aux:N #1 {
+ \cs_if_exist:cTF { fp_compare_#1: }
+ { \use:c { fp_compare_#1: } }
+ {
+ \group_end:
+ \prg_return_false:
+ }
+}
+% \end{macrocode}
+% For equality, the test is pretty easy as things are either equal or
+% they are not.
+% \begin{macrocode}
+\cs_new_protected_nopar:cpn { fp_compare_=: } {
+ \tex_ifnum:D \l_fp_input_a_sign_int = \l_fp_input_b_sign_int
+ \tex_ifnum:D \l_fp_input_a_integer_int = \l_fp_input_b_integer_int
+ \tex_ifnum:D \l_fp_input_a_decimal_int = \l_fp_input_b_decimal_int
+ \group_end:
+ \prg_return_true:
+ \tex_else:D
+ \group_end:
+ \prg_return_false:
+ \tex_fi:D
+ \tex_else:D
+ \group_end:
+ \prg_return_false:
+ \tex_fi:D
+ \tex_else:D
+ \group_end:
+ \prg_return_false:
+ \tex_fi:D
+}
+% \end{macrocode}
+% For comparitors life is a lot moe complex, as there are three cases for
+% the integer part (equality as well as greater and less than). The
+% code here is quite repetitive to keep speed up, and simply does
+% exhaustive checks.
+% \begin{macrocode}
+\cs_new_protected_nopar:cpn { fp_compare_>: } {
+ \tex_ifnum:D \l_fp_input_a_sign_int > \l_fp_input_b_sign_int
+ \group_end:
+ \prg_return_true:
+ \tex_else:D
+ \tex_ifnum:D \l_fp_input_a_sign_int < \l_fp_input_b_sign_int
+ \group_end:
+ \prg_return_false:
+ \tex_else:D
+ \tex_ifnum:D \l_fp_input_a_sign_int > \c_zero
+ \use:c { fp_compare_absolute_a > b: }
+ \tex_else:D
+ \use:c { fp_compare_absolute_a < b: }
+ \tex_fi:D
+ \tex_fi:D
+ \tex_fi:D
+}
+\cs_new_protected_nopar:cpn { fp_compare_<: } {
+ \tex_ifnum:D \l_fp_input_b_sign_int > \l_fp_input_a_sign_int
+ \group_end:
+ \prg_return_true:
+ \tex_else:D
+ \tex_ifnum:D \l_fp_input_b_sign_int < \l_fp_input_a_sign_int
+ \group_end:
+ \prg_return_false:
+ \tex_else:D
+ \tex_ifnum:D \l_fp_input_b_sign_int > \c_zero
+ \use:c { fp_compare_absolute_a < b: }
+ \tex_else:D
+ \use:c { fp_compare_absolute_a > b: }
+ \tex_fi:D
+ \tex_fi:D
+ \tex_fi:D
+}
+\cs_new_protected_nopar:cpn { fp_compare_absolute_a > b: } {
+ \tex_ifnum:D \l_fp_input_a_integer_int > \l_fp_input_b_integer_int
+ \group_end:
+ \prg_return_true:
+ \tex_else:D
+ \tex_ifnum:D \l_fp_input_a_integer_int < \l_fp_input_b_integer_int
+ \group_end:
+ \prg_return_false:
+ \tex_else:D
+ \tex_ifnum:D \l_fp_input_a_decimal_int > \l_fp_input_b_decimal_int
+ \group_end:
+ \prg_return_true:
+ \tex_else:D
+ \group_end:
+ \prg_return_false:
+ \tex_fi:D
+ \tex_fi:D
+ \tex_fi:D
+}
+\cs_new_protected_nopar:cpn { fp_compare_absolute_a < b: } {
+ \tex_ifnum:D \l_fp_input_b_integer_int > \l_fp_input_a_integer_int
+ \group_end:
+ \prg_return_true:
+ \tex_else:D
+ \tex_ifnum:D \l_fp_input_b_integer_int < \l_fp_input_a_integer_int
+ \group_end:
+ \prg_return_false:
+ \tex_else:D
+ \tex_ifnum:D \l_fp_input_b_decimal_int > \l_fp_input_a_decimal_int
+ \group_end:
+ \prg_return_true:
+ \tex_else:D
+ \group_end:
+ \prg_return_false:
+ \tex_fi:D
+ \tex_fi:D
+ \tex_fi:D
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{Formatting fixed point numbers}
+%
+% When transferring fixed points to higher level code it is desirable
+% to allow flexible formatting.
+%
+%\begin{macro}{\l_fp_round_precision_int}
+%\begin{macro}{\l_fp_remove_zeros_bool}
+%\begin{macro}{\l_fp_round_mode_tl}
+% \begin{macrocode}
+\keys_define:nn { fp } {
+ precision .int_set:N = \l_fp_round_precision_int ,
+ remove-trailing-zeros .bool_set:N = \l_fp_remove_zeros_bool ,
+ round-mode .choice: ,
+ round-mode
+ / half-even .tl_set:N = \l_fp_round_mode_tl ,
+ round-mode
+ / half-from-zero .tl_set:N = \l_fp_round_mode_tl ,
+ round-mode
+ / none .tl_set:N = \l_fp_round_mode_tl ,
+ round-mode
+ / truncate .tl_set:N = \l_fp_round_mode_tl ,
+}
+\keys_set:nn { fp } {
+ precision = 9 ,
+ remove-trailing-zeros = true ,
+ round-mode = none ,
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\begin{macro}{\fp_to_tl:NN}
+%\begin{macro}{\fp_to_tl:Nc}
+%\begin{macro}{\fp_to_tl:cN}
+%\begin{macro}{\fp_to_tl:cc}
+%\begin{macro}{\fp_gto_tl:NN}
+%\begin{macro}{\fp_gto_tl:Nc}
+%\begin{macro}{\fp_gto_tl:cN}
+%\begin{macro}{\fp_gto_tl:cc}
+%\begin{macro}[aux]{\fp_to_tl_aux:NNN}
+%\begin{macro}[aux]{\fp_remove_zeros:NNNNNNNNN}
+%\begin{macro}[aux]{\fp_remove_zeros_aux:w}
+%\begin{macro}[aux]{\fp_round_half-from-zero:}
+%\begin{macro}[aux]{\fp_round_from_zero:}
+%\begin{macro}[aux]{\fp_round_from_zero_aux:NNNNNNNNN}
+%\begin{macro}[aux]{\fp_round_from_zero_decimal:N}
+%\begin{macro}[aux]{\fp_round_from_zero_integer:}
+%\begin{macro}[aux]{\fp_round_half-even:}
+%\begin{macro}[aux]{\fp_round_even:}
+%\begin{macro}[aux]{\fp_round_even_aux:NNNNNNNNN}
+%\begin{macro}[aux]{\fp_round_even_decimal:N}
+%\begin{macro}[aux]{\fp_round_even_integer:}
+%\begin{macro}[aux]{\fp_round_none:}
+%\begin{macro}[aux]{\fp_round_truncate:}
+% The usual lead off with a series of wrapper functions.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_to_tl:NN {
+ \fp_to_tl_aux:NNN \tl_set:Nn
+}
+\cs_new_protected_nopar:Npn \fp_gto_tl:NN {
+ \fp_to_tl_aux:NNN \tl_gset:Nn
+}
+\cs_generate_variant:Nn \fp_to_tl:NN { Nc }
+\cs_generate_variant:Nn \fp_to_tl:NN { c }
+\cs_generate_variant:Nn \fp_to_tl:NN { cc }
+\cs_generate_variant:Nn \fp_gto_tl:NN { Nc }
+\cs_generate_variant:Nn \fp_gto_tl:NN { c }
+\cs_generate_variant:Nn \fp_gto_tl:NN { cc }
+% \end{macrocode}
+% The main body of the conversion follows the pattern of reading the
+% \texttt{fp} then processing it. Rounding takes place first, so
+% that zero stripping is easier. This may involve loosing the decimal
+% part entirely.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_to_tl_aux:NNN #1#2#3 {
+ \group_begin:
+ \fp_read:N #2
+ \use:c { fp_round_ \l_fp_round_mode_tl :}
+ \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
+ \tl_set:Nx \l_fp_tmp_tl
+ {
+ \tex_ifnum:D \l_fp_input_a_sign_int < \c_zero
+ -
+ \tex_fi:D
+ \int_use:N \l_fp_input_a_integer_int
+ \intexpr_compare:nNnT { \l_fp_round_precision_int } > { \c_zero }
+ {
+ .
+ \bool_if:NTF \l_fp_remove_zeros_bool
+ {
+ \exp_after:wN \use_i:nn
+ \exp_after:wN \fp_remove_zeros:NNNNNNNNN
+ }
+ { \exp_after:wN \use_none:n }
+ \int_use:N \l_fp_input_a_decimal_int
+ }
+ }
+ \exp_after:wN \group_end: \exp_after:wN
+ #1 \exp_after:wN #3 \exp_after:wN { \l_fp_tmp_tl }
+}
+% \end{macrocode}
+% For removing zeros, the code above ensures there will be exactly
+% \( 9 \) tokens to deal with. The idea here is to go through them one
+% at a time and see if the remained is equal to zero. The input can
+% then be discarded if the precision in the output is correct. Speed
+% is not quite so vital here so everything is coded in \LaTeX3 rather
+% than primitives. This approach avoids needing to reverse the input.
+% \begin{macrocode}
+\cs_new_nopar:Npn \fp_remove_zeros:NNNNNNNNN #1#2#3#4#5#6#7#8#9 {
+ \fp_remove_zeros_aux:w #1#2#3#4#5#6#7#8#9 \q_stop 1
+}
+\cs_new_nopar:Npn \fp_remove_zeros_aux:w #1#2 \q_stop #3 {
+ #1
+ \intexpr_compare:nNnTF { 0 #2 } = { \c_zero }
+ {
+ \intexpr_compare:nNnF { \l_fp_round_precision_int } < { #3 + 1 }
+ {
+ \intexpr_compare:nNnT {#3} < { 9 }
+ { \fp_remove_zeros_aux:w #2 \q_stop { #3 + 1 } }
+ }
+ }
+ {
+ \intexpr_compare:nNnT {#3} < { 9 }
+ { \fp_remove_zeros_aux:w #2 \q_stop { #3 + 1 } }
+ }
+}
+% \end{macrocode}
+% Rounding away from zero is relatively easy, as it only depends on
+% the digit immediately before the rounded position. The code here
+% therefore does a fast reversal of the direct of the input, then
+% checks the position before considering the size of the digit itself.
+% The position here refers to the digit that will be rounded, which is
+% therefore out by one from the digit being considered during the loop.
+% \begin{macrocode}
+\cs_new_protected_nopar:cpn { fp_round_half-from-zero: } {
+ \tex_ifnum:D \l_fp_round_precision_int < \c_nine
+ \exp_after:wN \fp_round_from_zero:
+ \tex_fi:D
+}
+\cs_new_protected_nopar:Npn \fp_round_from_zero: {
+ \bool_set_false:N \l_fp_round_carry_bool
+ \l_fp_round_position_int \c_eight
+ \tl_clear:N \l_fp_round_decimal_tl
+ \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
+ \exp_after:wN \use_i:nn \exp_after:wN
+ \fp_round_from_zero_aux:NNNNNNNNN
+ \int_use:N \l_fp_input_a_decimal_int
+}
+\cs_new_protected_nopar:Npn \fp_round_from_zero_aux:NNNNNNNNN
+ #1#2#3#4#5#6#7#8#9 {
+ \fp_round_from_zero_decimal:N #9#8#7#6#5#4#3#2#1
+ \fp_round_from_zero_integer:
+}
+\cs_new_protected_nopar:Npn \fp_round_from_zero_decimal:N #1 {
+ \tex_ifnum:D \l_fp_round_position_int < \l_fp_round_precision_int
+ \bool_if:NTF \l_fp_round_carry_bool
+ { \l_fp_tmp_int \etex_numexpr:D #1 + \c_one \scan_stop: }
+ { \l_fp_tmp_int \etex_numexpr:D #1 \scan_stop: }
+ \tex_ifnum:D \l_fp_tmp_int = \c_ten
+ \l_fp_tmp_int \c_zero
+ \tex_else:D
+ \bool_set_false:N \l_fp_round_carry_bool
+ \tex_fi:D
+ \tl_set:Nx \l_fp_round_decimal_tl
+ { \int_use:N \l_fp_tmp_int \l_fp_round_decimal_tl }
+ \tex_else:D
+ \tl_set:Nx \l_fp_round_decimal_tl { 0 \l_fp_round_decimal_tl }
+ \tex_ifnum:D \l_fp_round_position_int = \l_fp_round_precision_int
+ \tex_ifnum:D #1 > \c_four
+ \bool_set_true:N \l_fp_round_carry_bool
+ \tex_fi:D
+ \tex_fi:D
+ \tex_fi:D
+ \tex_advance:D \l_fp_round_position_int \c_minus_one
+ \tex_ifnum:D \l_fp_round_position_int > \c_minus_one
+ \exp_after:wN \fp_round_from_zero_decimal:N
+ \tex_fi:D
+}
+\cs_new_protected_nopar:Npn \fp_round_from_zero_integer: {
+ \bool_if:NT \l_fp_round_carry_bool
+ { \tex_advance:D \l_fp_input_a_integer_int \c_one }
+ \l_fp_input_a_decimal_int \l_fp_round_decimal_tl \scan_stop:
+}
+% \end{macrocode}
+% The general outline is similar when rounding where ties go to the
+% nearest even number. However, life is more complicated as there is a
+% need to track the discarded digits, and to see whether the digit to
+% round is odd or even. This is done by tracking the discarded digits.
+% When reaching the digit to check for rounding, the discards are used
+% to indicate if there is an exact half to take into account. When the
+% rounding takes place without an exact half, things are the same as
+% for the \enquote{away from zero} approach. When rounding an exact
+% half, there is an odd/even test before applying any modification.
+% \begin{macrocode}
+\cs_new_protected_nopar:cpn { fp_round_half-even: } {
+ \tex_ifnum:D \l_fp_round_precision_int < \c_nine
+ \exp_after:wN \fp_round_even:
+ \tex_fi:D
+}
+\cs_new_protected_nopar:Npn \fp_round_even: {
+ \bool_set_false:N \l_fp_round_carry_bool
+ \l_fp_round_position_int \c_eight
+ \tl_clear:N \l_fp_round_decimal_tl
+ \int_zero:N \l_fp_round_discard_int
+ \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
+ \exp_after:wN \use_i:nn \exp_after:wN
+ \fp_round_even_aux:NNNNNNNNN
+ \int_use:N \l_fp_input_a_decimal_int
+}
+\cs_new_protected_nopar:Npn \fp_round_even_aux:NNNNNNNNN
+ #1#2#3#4#5#6#7#8#9 {
+ \fp_round_even_decimal:N #9#8#7#6#5#4#3#2#1
+ \fp_round_even_integer:
+}
+\cs_new_protected_nopar:Npn \fp_round_even_decimal:N #1 {
+ \tex_ifnum:D \l_fp_round_position_int < \l_fp_round_precision_int
+ \bool_if:NTF \l_fp_round_carry_bool
+ {
+ \tex_ifnum:D \l_fp_round_discard_int = \c_zero
+ \l_fp_round_discard_int \c_one
+ \tex_ifodd:D #1 \scan_stop:
+ \l_fp_tmp_int \etex_numexpr:D #1 + \c_one \scan_stop:
+ \tex_else:D
+ \l_fp_tmp_int \etex_numexpr:D #1 \scan_stop:
+ \tex_fi:D
+ \tex_else:D
+ \l_fp_tmp_int \etex_numexpr:D #1 + \c_one \scan_stop:
+ \tex_fi:D
+ }
+ { \l_fp_tmp_int \etex_numexpr:D #1 \scan_stop: }
+ \tex_ifnum:D \l_fp_tmp_int = \c_ten
+ \l_fp_tmp_int \c_zero
+ \tex_else:D
+ \bool_set_false:N \l_fp_round_carry_bool
+ \tex_fi:D
+ \tl_set:Nx \l_fp_round_decimal_tl
+ { \int_use:N \l_fp_tmp_int \l_fp_round_decimal_tl }
+ \tex_else:D
+ \tl_set:Nx \l_fp_round_decimal_tl { 0 \l_fp_round_decimal_tl }
+ \tex_ifnum:D \l_fp_round_position_int = \l_fp_round_precision_int
+ \tex_ifnum:D #1 > \c_four
+ \bool_set_true:N \l_fp_round_carry_bool
+ \tex_ifnum:D #1 = \c_five
+ \tex_else:D
+ \l_fp_round_discard_int \c_one
+ \tex_fi:D
+ \tex_fi:D
+ \tex_else:D
+ \tex_advance:D \l_fp_round_discard_int #1 \scan_stop:
+ \tex_fi:D
+ \tex_fi:D
+ \tex_advance:D \l_fp_round_position_int \c_minus_one
+ \tex_ifnum:D \l_fp_round_position_int > \c_minus_one
+ \exp_after:wN \fp_round_even_decimal:N
+ \tex_fi:D
+}
+\cs_new_protected_nopar:Npn \fp_round_even_integer: {
+ \bool_if:NT \l_fp_round_carry_bool
+ {
+ \tex_ifnum:D \l_fp_round_discard_int = \c_zero
+ \tex_ifodd:D \l_fp_input_a_integer_int
+ \tex_advance:D \l_fp_input_a_integer_int \c_one
+ \tex_fi:D
+ \tex_else:D
+ \tex_advance:D \l_fp_input_a_integer_int \c_one
+ \tex_fi:D
+ }
+ \l_fp_input_a_decimal_int \l_fp_round_decimal_tl \scan_stop:
+}
+% \end{macrocode}
+% The only task that is needed when not rounding is to ensure that
+% the zero-stripping function will remove things reliably. This is
+% done by setting the precision to one digit: no rounding will always
+% leave at least one decimal digit, even if it is zero.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_round_none: {
+ \l_fp_round_precision_int \c_one
+}
+% \end{macrocode}
+% Truncating input is done by using the \cs{tex_divide:D} primitive
+% as this turns out to be the most convenient method to do this.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_round_truncate: {
+ \intexpr_compare:nNnF { \l_fp_round_precision_int } > { 8 }
+ {
+ \intexpr_compare:nNnTF { \l_fp_round_precision_int } < { 1 }
+ { \l_fp_input_a_decimal_int \c_zero \scan_stop: }
+ {
+ \int_set:Nn \l_fp_tmp_int
+ {
+ \prg_replicate:nn { 9 - \l_fp_round_precision_int }
+ { 10 * }
+ 1
+ }
+ \tex_divide:D \l_fp_input_a_decimal_int \l_fp_tmp_int
+ \tex_multiply:D \l_fp_input_a_decimal_int \l_fp_tmp_int
+ }
+ }
+}
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+%\subsection{Messages}
+%
+%\begin{macro}{\fp_msg_overflow:}
+% To avoid expansion issues above, the messages are all set up as
+% functions.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_msg_overflow: {
+ \msg_kernel_error:nn { fpu } { overflow }
+}
+% \end{macrocode}
+%\end{macro}
+%
+% \begin{macrocode}
+\msg_kernel_new:nnnn { fpu } { overflow }
+ { Arithmetic~overflow. }
+ {
+ The~calculation~requested~exceeds~the~capacity \\
+ of~the~fixed-point~unit.
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+%\end{implementation}
+%
+%\PrintChanges
+%
+%\PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/expl3/l3intexpr.dtx b/Master/texmf-dist/source/latex/expl3/l3intexpr.dtx
index 4c43e63e6db..71801f8780d 100644
--- a/Master/texmf-dist/source/latex/expl3/l3intexpr.dtx
+++ b/Master/texmf-dist/source/latex/expl3/l3intexpr.dtx
@@ -36,7 +36,7 @@
\RequirePackage{l3names}
%</driver|package>
%\fi
-\GetIdInfo$Id: l3intexpr.dtx 1086 2009-03-20 19:29:35Z morten $
+\GetIdInfo$Id: l3intexpr.dtx 1957 2010-06-15 06:33:43Z mittelba $
{L3 Integer Expressions}
%\iffalse
%<*driver>
@@ -463,11 +463,32 @@
% \begin{macro}[TF]{\intexpr_compare:nNn}
% More efficient but less natural in typing.
% \begin{macrocode}
-\prg_set_conditional:Npnn \intexpr_compare:nNn #1#2#3{p,TF,T,F}{
+\prg_set_conditional:Npnn \intexpr_compare:nNn #1#2#3{p}{
\if_intexpr_compare:w \intexpr_eval:w #1 #2 \intexpr_eval:w #3
\intexpr_eval_end:
\prg_return_true: \else: \prg_return_false: \fi:
}
+\cs_set_nopar:Npn \intexpr_compare:nNnT #1#2#3 {
+ \tex_ifnum:D \etex_numexpr:D #1 #2 \etex_numexpr:D #3 \scan_stop:
+ \tex_expandafter:D \use:n
+ \tex_else:D
+ \tex_expandafter:D \use_none:n
+ \tex_fi:D
+}
+\cs_set_nopar:Npn \intexpr_compare:nNnF #1#2#3 {
+ \tex_ifnum:D \etex_numexpr:D #1 #2 \etex_numexpr:D #3 \scan_stop:
+ \tex_expandafter:D \use_none:n
+ \tex_else:D
+ \tex_expandafter:D \use:n
+ \tex_fi:D
+}
+\cs_set_nopar:Npn \intexpr_compare:nNnTF #1#2#3 {
+ \tex_ifnum:D \etex_numexpr:D #1 #2 \etex_numexpr:D #3 \scan_stop:
+ \tex_expandafter:D \use_i:nn
+ \tex_else:D
+ \tex_expandafter:D \use_ii:nn
+ \tex_fi:D
+}
% \end{macrocode}
% \end{macro}
% \end{macro}
diff --git a/Master/texmf-dist/source/latex/expl3/l3names.dtx b/Master/texmf-dist/source/latex/expl3/l3names.dtx
index 651be378791..99b224d62c5 100644
--- a/Master/texmf-dist/source/latex/expl3/l3names.dtx
+++ b/Master/texmf-dist/source/latex/expl3/l3names.dtx
@@ -128,7 +128,7 @@
\RequirePackage{l3names}
%</driver>
%\fi
-\GetIdInfo$Id: l3names.dtx 1853 2010-03-21 09:11:08Z joseph $
+\GetIdInfo$Id: l3names.dtx 1981 2010-07-11 07:28:30Z will $
{L3 Experimental Naming Scheme for TeX Primitives}
%
%
@@ -324,6 +324,10 @@
\endlinechar =\the \endlinechar \relax
\catcode 95=\the \catcode 95 \relax
\catcode 58=\the \catcode 58 \relax
+ \catcode 124=\the \catcode 124 \relax
+ \catcode 38=\the \catcode 38 \relax
+ \catcode 94=\the \catcode 94 \relax
+ \catcode 34=\the \catcode 34 \relax
\noexpand\fi
}
\catcode126=10\relax % tilde is a space char.
@@ -332,6 +336,10 @@
\endlinechar=32\relax % endline is space
\catcode95=11\relax % underscore letter
\catcode58=11\relax % colon letter
+\catcode124=12\relax % vert bar, other
+\catcode38=4\relax % ampersand, alignment token
+\catcode34=12\relax % doublequote, other
+\catcode94=7\relax % caret, math superscript
% \end{macrocode}
%
% \subsection{Setting up primitive names}
@@ -981,6 +989,10 @@
\tex_endlinechar:D =\tex_the:D \tex_endlinechar:D \tex_relax:D
\tex_catcode:D 95=\tex_the:D \tex_catcode:D 95 \tex_relax:D
\tex_catcode:D 58=\tex_the:D \tex_catcode:D 58 \tex_relax:D
+ \tex_catcode:D 124=\tex_the:D \tex_catcode:D 124 \tex_relax:D
+ \tex_catcode:D 38=\tex_the:D \tex_catcode:D 38 \tex_relax:D
+ \tex_catcode:D 94=\tex_the:D \tex_catcode:D 94 \tex_relax:D
+ \tex_catcode:D 34=\tex_the:D \tex_catcode:D 34 \tex_relax:D
\tex_noexpand:D \tex_fi:D
}
\tex_def:D \ExplSyntaxStatus { 1 }
@@ -990,6 +1002,10 @@
\tex_endlinechar:D =32 \tex_relax:D % endline is space
\tex_catcode:D 95=11 \tex_relax:D % underscore letter
\tex_catcode:D 58=11 \tex_relax:D % colon letter
+ \tex_catcode:D 124=11 \tex_relax:D % vertical bar, other
+ \tex_catcode:D 38=4 \tex_relax:D % ampersand, alignment token
+ \tex_catcode:D 94=7 \tex_relax:D % caret, math superscript
+ \tex_catcode:D 34=12 \tex_relax:D % doublequote, other
\tex_fi:D
}
% \end{macrocode}
@@ -1138,7 +1154,7 @@
% as the packages in this distribution do like this:
% \begin{verbatim}
% \RequirePackage{l3names}
-% \GetIdInfo$Id: l3names.dtx 1853 2010-03-21 09:11:08Z joseph $
+% \GetIdInfo$Id: l3names.dtx 1981 2010-07-11 07:28:30Z will $
% {L3 Experimental Box module}
% \ProvidesExplPackage
% {\filename}{\filedate}{\fileversion}{\filedescription}