\svnInfo $Id$
\section{High-precision and interval arithmetic with MetaPost}
\label{hparith}
In addition to the fixed-point arithmetics inherited from \MF, MetaPost
can also do higher-precision arithmetics. In total, MetaPost can handle
numeric quantities in five internal representation formats or number
systems. Number systems differ in rounding errors\index{rounding error}
introduced by and the speed of arithmetic operations. Simply storing a
numeric value in a variable may already introduce a rounding error, so
that can already be considered an arithmetic operation.
The internal representation format used for numeric quantities can be
determined by a command-line switch
\texttt{-numbersystem}\index{command-line!mpost?\texttt{mpost}!-numbersystem?\texttt{-numbersystem}}
when invoking the MetaPost executable. Argument is a string and can be
one of \texttt{scaled}, \texttt{double}, \texttt{binary}, \texttt{interval} or
\texttt{decimal}. The argument is stored in an internal string variable
\texttt{numbersystem}\index{numbersystem?\texttt{numbersystem}}\label{Dnumbersystem}.
Assigning a value to this variable at run-time triggers an error.
The \texttt{scaled}\index{scaled?\texttt{scaled}} number system refers
to 32~bit fixed-point arithmetics described in Section~\ref{datatypes}.
This is the default number system. Precision is ca.~10~decimal digits,
5 digits before and after the comma. All arithmetic operations are done
in software.
The \texttt{double}\index{double?\texttt{double}} number system does
IEEE standard floating-point arithmetics with 64~bits (or double)
precision. In the internal representation, double floating-point
numbers use $52+1$~bits for the mantissa, which determines precision,
11~bits for the exponent, which determines the valid range of numbers,
and one bit for the sign. The smallest absolute value that can be
represented is ca.~$2.2\cdot10^{-308}$, the largest value is
ca.~$1.8\cdot10^{308}$. The 53~bit mantissa makes for a precision of
ca.~15 decimal digits. The smallest possible difference between two
distinct numbers in double floating-point number representation is
$2^{-53} \approx 1.1\cdot10^{-16}$. The largest integer value that can
be represented exactly is $2^{53}-1 \approx 9,0\cdot10^{15}$. Variable
\texttt{warningcheck}\index{warningcheck?\texttt{warningcheck}} is set
to $2^{52}$ in \texttt{double} mode. Arithmetic operations make use of
a hardware floating-point unit (FPU), if available.
While the IEEE double precision floating-point format provides plenty
room for storing numeric values, still, precision and range are finite
and fix. For users that need higher precision or range, MetaPost
provides support for (almost) arbitrary precision floating-point
arithmetics. The \texttt{binary}\index{binary?\texttt{binary}} number
system is similar to the \texttt{double} number system, except that the
number of bits used for the mantissa is not fixed, but variable.
Precision is determined by an internal variable
\texttt{numberprecision}\index{numberprecision?\texttt{numberprecision}}\label{Dnumberprecision}
in decimal digits. Valid numbers are in the range 1 to 1000. Higher
values make for better precision at the expense of performance of
arithmetic operations. Default precision is 34~decimal digits
(ca.~113~bits in the mantissa). Exponent in the internal representation
is an integer in the range $[-9,999,999; +9,999,999]$. All arithmetic
operations are done in software using the MPFR library~\cite{lib:mpfr}
and are usually orders of magnitude slower than in \texttt{double} mode.
The \index{interval?interval number system}\texttt{interval} number
system MPFI~\cite{lib:mpfi}, introduced in version \texttt{2.10}, is built on the top of the MPFR library
and an interval quantity \texttt{[}\textit{number}\texttt{,}\textit{number}\texttt{]} is created with
\begin{center}\index{interval\_set?\texttt{interval\_set}}\label{Dintervalset}\texttt{w := interval\_set(}\textit{number}\texttt{,}\textit{number}\texttt{);}\end{center}
An interval is a set, the left extrema being
\begin{center}\index{interval\_get\_left\_endpoint?\texttt{interval\_get\_left\_endpoint}}\label{Dintervalleft}\texttt{l := interval\_get\_left\_endpoint(}\textit{interval}\texttt{);}\end{center}
and the right extrema
\begin{center}\index{interval\_get\_right\_endpoint?\texttt{interval\_get\_right\_endpoint}}\label{Dintervalright}\texttt{r := interval\_get\_right\_endpoint(}\textit{interval}\texttt{);}\end{center}
and it's always $l\leq r$\,; a number \texttt{x} is always seen as the interval \texttt{[x,x]}, i.e. a set with one element.
At first glance, interval arithmetic can be confusing: if $w$ is an interval,
$w*w$ is the set $\left\{ x*y: x\in w, y\in w\right\}$, but $f(w)=w^2$ is the set $\left\{f(x): x\in w\right\} = \left\{x^2: x\in w\right\}$:
if $w=[-1,1]$ then $w*w=[-1,1]$ and $w^2=[0,1]$. On the other hand, it's easy to verify that $w*w*w = w^3$ always. For this reason,
given that currently the
implementation of the MetaPost functions in MPFI mimics those of MPFR and they are not adapted to the interval arithmetic,
the main utility of interval mode is the implementation of algorithms in MetaPost language.
Number system \texttt{decimal}\index{decimal?\texttt{decimal}} provides
arbitrary precision floating-point arithmetics similar to the
\texttt{binary} number system. Except that it uses a base of~10 for the
internal representation instead of a base of~2. The point is that with
base~2 floating-point numbers some decimal numbers cannot be represented
exactly, among them such strange numbers like $0.1$. In a base~2
floating-point number format, this value has an infinit repeating
representation, which cannot be stored in a mantissa of finite precision
without introducing a rounding error. While such initial errors may be
small, they use to accummulate when doing calculations. Sometimes
increasing precision by switching from \texttt{double} to
\texttt{binary} mode is sufficient to get satisfying results again. On
the other hand, there's a demand for doing calculations exactly like
humans do with pencil and paper, e.g., for certain financial
calculations. The only way to ensure exact result is switching base of
the internal representation to~10. Again, precision can be determined
by assigning a value to variable
\texttt{numberprecision}\index{numberprecision?\texttt{numberprecision}}.
Valid numbers are in the range 1 to 1000. Default precision is
34~decimal digits. Exponent in the internal representation is an
integer in the range $[-9,999,999; +9,999,999]$. All arithmetic
operations are done in software using the decNumber
library~\cite{lib:decnumber} and are usually slower than in
\texttt{binary} mode.
In all number systems except the traditional fixed-point
(\texttt{scaled}) number system, numbers can be given in scientific
notation, i.e., input like \texttt{1.23e4} is interpreted as the value
$12,300$ instead of the product of the numeric value $1.23$ and (array)
variable \verb|e[4]|.
%%% Local Variables:
%%% mode: latex
%%% TeX-PDF-mode: t
%%% TeX-master: "mpman"
%%% End: