% from 20.3.1989 hk, version 0.03
% revised 5.11.1989 hk, version 0.30
% arithmetic part 26.1.1990 hk

%\setcounter{chapter}{5}
%\setcounter{section}{2}
\section{Arbitrary Precision Floating Point Arithmetic}

The arbitrary precision floating point numbers are 
called {\bf floating point numbers} for short.
We will first discuss the representation 
of floating point numbers by lists.

{\bf Note:} 
Let $a \in \Q$, then there 
exists an integer $e \in \Z$ and 
a rational number $m \in \Q$ 
with $\frac{1}{2} \leq \vert m \vert < 1$
such that
\begin{displaymath} 
       a = m \cdot 2^e.
\end{displaymath} 
In this case $e = \lfloor \log_2( \vert a \vert ) \rfloor + 1$.

The binary precision $z$ of a floating point number is
the number of binary digits of the fraction part.
We call $m' = \lfloor m \cdot 2^z \rfloor \in \Z$
the fraction part (also called mantissa) of the floating point 
number $a$ and we call $e$ the exponent of $a$.

{\bf Definition:} List representation of floating point numbers.
\begin{quote}
       $0 \in \Q$ is represented by the list $(0,0)$.
       \\
       $a \in \Q$, $a \neq 0$ with $-\beta < e < \beta$, 
       is represented by the list $(e',m')$. 
       $e = e' \in \A$ and $m' \in \I$ are 
       represented as atom respectively integer.
       $e, m'$ defined as before.
       \\
       For $a \in \Q$ with $e \leq -\beta$ or $\beta \leq e$ 
       there is no representation defined.
\end{quote}
\index{list! representation}\index{floating point! representation}
\index{representation}

Recall that $\beta = 2^{\zeta}$ is a power of 2, $\zeta = 29$.
The binary precision $z$ is determined from the 
decimal precision $d$ in the following way. 
Let 
\begin{displaymath}
    \rho = \lceil \log_{\beta}(10^d) \rceil 
\end{displaymath}
then 
\begin{displaymath}
    z = \lfloor \log_2(\beta^\rho) \rfloor - 1 
      = \frac{\rho}{\zeta} - 1.
\end{displaymath}
The fraction part $m'$ of a floating point number
is then an integer with 
$\lceil \log_2( \vert m' \vert ) \rceil = z$ and 
so $\lceil \log_{\beta}( \vert m' \vert ) \rceil = \rho$. 

{\bf Example:} \\
Let $d = 20$, i.e. the desired decimal precision is $20$
decimal digits. Then
$\lceil \log_{\beta}(10^{20}) \rceil$ $= 3 = \rho$ 
and we have $z = \zeta \rho - 1 = 29 \cdot 3 - 1 = 86$.
\begin{quote}
    $\frac{1}{2} = \frac{1}{2} \cdot 2^0$ is 
    represented as $(0,(0,0,134217728))$, 
    since $e = 0$, and $\lfloor \frac{1}{2} \cdot 2^z \rfloor$ 
    $= 0 \beta^0 + 0 \beta^2 + 134217728 \beta^2$
    which is represented by $(0,0,134217728)$.
    \\
    $1 = \frac{1}{2} \cdot 2^1$ is represented 
         by $(1,(0,0,134217728))$, \\ 
    $\frac{1}{4} = \frac{1}{2} \cdot 2^{-1}$ is represented 
         by $(-1,(0,0,134217728))$ \\ and 
    $-2 = \frac{-1}{2} \cdot 2^2$ is represented 
         by $(2,(0,0,-134217728))$. 
\end{quote}


\subsection{Algorithms}

The programs of the most important floating point algorithms 
and their complexity are summarized in the following.

\def\F{{\cal F}}
Let
$\A$ be the set of atoms,
$\L$ be the set of lists,
$\O = \A \cup \L$ be the set of objects,
$\I = \{ x \in \O: \ x$ represents an element of ${\rm \bf Z} \}$ 
be the set of integers, 
$\R = \{ x \in \O: \ x$ represents an element of ${\rm \bf Q} \}$ 
be the set of rational numbers and 
$\F = \{ x \in \O: \ x$ represents a floating point number$\}$ 
be the set of floating point numbers. 
\index{floating point! algorithms}\index{floating point}
Let $\rho = L(a)$ denote the $\beta$--length 
of the fraction part $m'$ of a floating point number $a$.
The length of integers and rational numbers are defined as in
the previous section.
We will also write $L(a)$ for $O(L(a))$, i.e. we will not count for 
constant factors.
The computing time functions $t, \tma, \tmi, \ta$ 
are defined as before in section \ref{secCOMPL}.
\index{complexity}


\begin{deflist}{$c \gets APPROD(a,b)$}
\item[$APSPRE(n)$] $n \in \A$. 
     The precision of floating point numbers is set to
     $n$ decimal digits.
     $\tma = \tma_{{\rm IEXP}} = n^2 = O(\rho^2)$, 
     $\cma = 2 n = O(2 \rho)$. 
     \index{APSPRE}
\item[$b \gets APFINT(a)$] $a \in \I$, $b \in \F$. 
     $b = m' 2^{e'}$ is the embedding of 
     the integer $a$ into the floating point numbers. 
     Since $a$ is shifted 
     $\tma = L(a) + \vert L(a) - L(b) \vert$ 
     $ = \max \{ L(a), \rho \}$,
     $\cma = \rho$, $\tmi = L(a)$, $\cmi = 0$.
     \index{APFINT}
\item[$b \gets APFRN(a)$] $a \in \R$, $b \in \F$. 
     $b = m' 2^{e'}$ is the embedding of 
     the rational number $a$ into the floating point numbers. 
     The numerator and denominator of $a$ are converted 
     to floating point numbers, then their quotient is formed.
     $\tma = 2 \tma_{{\rm APFINT}} + \tma_{{\rm APQ}}$ 
     $= 2 \max \{ L(a), \rho \} + \rho^2$, 
     $\cma = 2 \rho + \rho^2$. 
     \index{APFRN}
\item[$b \gets RNFAP(a)$] $a \in \F$, $b \in \R$. 
     $b = \frac{m}{2^{-e}}$ is the
     the rational number $b$ which corresponds to 
     the floating point number $a$. 
     $b$ is reduced to lowest terms.
     $\tma = \tma_{{\rm IEXP}} + \tma_{{\rm RNRED}}$ 
     $= e^2 + {\rm max}\{ \rho, \frac{e}{\zeta} \}^2$, 
     $\cma = e^2 + {\rm max}\{ \rho, \frac{e}{\zeta} \}^2$. 
     \index{RNFAP}
\item[$b \gets APNEG(a)$] $a, b \in \F$. 
     $b = -a$ is the negative of $a$.
     The fraction part of $a$ is negated, so 
     $t = t_{{\rm INEG}} = \rho$, $c = \rho$. 
     \index{APNEG}
\item[$s \gets APSIGN(a)$] $a \in \F$, $s \in \{-1,0,+1\}$. 
     $s = {\rm sign}(a)$ is the sign of $a$.
     The integer sign of the fraction part of $a$ is determined, so
     $\tma = \rho$, $\tmi = 1$, $c = 0$. 
     \index{APSIGN}
\item[$b \gets APABS(a)$] $a, b \in \F$. 
     $b = \vert a \vert$ is the absolute value of $a$.
     The fraction part of $a$ is possibly negated, so 
     $\tma = \tma_{{\rm APNEG}} = \rho$, $\cma = \rho$. 
     $\tmi = 1$, $\cmi = 0$. 
     \index{APABS}
\item[$s \gets APCMPR(a,b)$] $a, b \in \F$, $s \in \{-1,0,+1\}$. 
     $s = {\rm sign}(a-b)$ is the sign of the difference of 
     $a$ and $b$.
     The fraction part of $a$ and $b$ must be compared
     if the signs of the fraction parts and the 
     exponents are equal, so 
     $\tma = \rho$, $\tmi = 1$, $c = 0$. 
     \index{APCMPR}
\item[$c \gets APPROD(a,b)$] $a, b, c \in \F$. 
     $c = a \cdot b$ is the product of $a$ and $b$.
     The fraction parts of $a$ and $b$ are multiplied
     the result is then truncated,
     so $t = \rho^2$, $c = \rho^2$. 
     \index{APPROD}
\item[$c \gets APQ(a,b)$] $a, b, c \in \F$. 
     $c = a / b$ is the quotient of $a$ and $b$.
     The fraction part of $a$ is shifted by $2^z$ 
     and then an integer quotient is computed, so 
     $t = 2 \rho^2$, $c = \rho^2$. 
     \index{APQ}
\item[$c \gets APSUM(a,b)$] $a, b, c \in \F$. 
     $c = a + b$ is the sum of $a$ and $b$.
     The fraction part of $a$ or $b$ is shifted
     to bring the decimal points in the same place, then 
     the integers are added and normalized.
     Let $e_a$ and $e_b$ be the exponents of $a$ and $b$ 
     respectively. Assume further that 
     $\vert e_a - e_b \vert < z$, since otherwise nothing is to 
     be done, then
     $\tma = \tma_{{\rm IMP2}} + \tma_{{\rm ISUM}}+ \tma_{{\rm APFINT}}$ 
     $ = L(2^{\vert e_a - e_b \vert}) + 2\rho + 2\rho = O(2\rho)$.
     $\cma = 2\rho$, $\tmi = \rho$, $\cmi = \rho$.
     \index{APSUM}
\item[$c \gets APDIFF(a,b)$] $a, b, c \in \F$. 
     $c = a - b$ is the difference of $a$ and $b$.
     $b$ is negated, then the sum of $a$ and $-b$ is computed.
     $\tma = \tma_{{\rm APSUM}}$, $\tmi = \rho$. 
     \index{APDIFF}
\item[$b \gets APEXP(a,n)$] $a, b \in \F$, $n \in \A$. 
     $b = a^n$ is the $n$-th power of $a$ (exponentiation).
     The binary exponentiation method is used as described
     with $IEXP$. Since the length of the products 
     are always $\rho$ we have to count the number of products 
     and so $\tma = \log_2(n) \rho^2$. 
     \index{APEXP}
\item[$b \gets APROOT(a,n)$] $a, b \in \F$, $n \in \A$. 
     $b = \sqrt[n]{a}$ is the $n$-th root of $\vert a \vert$.
     $b$ is computed by Newtons method. 
     The most expensive part is the computation of $a^n$, so
     $\tma = \log_2(n) \rho^2$.
     \index{APROOT}
\item[$a \gets APPI()$] $a \in \F$. 
     $a = \pi$.
     $\pi$ is computed by the method of Salamin
     using the arithmetic--geometric mean approximation 
     for an elliptic integral representation of $\pi$.
     $\tma = {\rm const} \rho^2$, since square roots are computed.
     \index{APPI}
\item[$a \gets APREAD()$] $a \in \F$.
     $APREAD$ is be defined as $APFRN( RNDRD() )$ 
     and the accepted syntax is that of $RNDWR$.
     \index{RNDWR}\index{APREAD}\index{APFRN}
\item[$APWRIT(a)$] $a \in \F$.
     The floating point number $a$ is written to 
     the current output stream.
     The syntax is:
\begin{verbatim}
rat = int "." unsigned-int 
              [ "E" unsigned-beta-int ]
\end{verbatim}
     This syntax is accepted by $RNDRD$ for input.
     \index{syntax}\index{floating point! syntax}
     \index{APWRIT}
\end{deflist}
This concludes the summary of 
floating point number arithmetic functions.

{\bf Note:} When the precision of the 
floating point numbers is changed, then the 
already existing numbers are not automatically converted
to the new precision. The conversion can be
accomplished by first converting the floating point number to 
a rational number. Then change the precision and finally reconvert
the rational number to a floating point number.

{\bf Example:} Assume the current decimal precision 
is $d_2$ and we want to convert numbers which are 
represented in precision $d_1$. The following
algorithm does the conversion:
\begin{verbatim}
       PROCEDURE Crep(a,d1,d2);
       (*Change the representation of the 
       floating point number a, with precision d1 to
       precision d2.*)
       VAR   r: LIST;
       BEGIN 
       (*1*) (*set old precision and convert. *)
             APSPRE(d1); r:=RNFAP(a);
       (*2*) (*set new precision and convert. *)
             APSPRE(d2); r:=APFRN(r);
             RETURN(r);
       (*3*) END Crep.
\end{verbatim}

For illustration we list 
the algorithms \verb/APFINT/ and \verb/APSUM/ in Modula--2
in MAS.
The function of the algorithms should be clear from the 
step comments and the floating point number representation 
discussed before.

{\footnotesize
\begin{verbatim}
  PROCEDURE APFINT(N: LIST): LIST;
  (*Arbitrary precision floating point from integer.
  The integer N is converted to the arbitrary precision
  floating point number A.*)
  VAR   A, EL, FL, ML: LIST;
  BEGIN
  (*1*) (*n=0.*)
        IF N = 0 THEN A:=APCOMP(0,0); RETURN(A); END;
  (*2*) (*normalize.*) EL:=ILOG2(N); FL:=EL-1-APPR2; (*1=log2(2).*)
        IF FL >= 0 
           THEN ML:=IDP2(N,FL); (*truncate*)
           ELSE ML:=IMP2(N,-FL); (*fill up*) END; 
  (*3*) (*round.*) ML:=ISUM(ML,1); 
        ML:=IDP2(ML,1);
  (*4*) (*finish.*) A:=APCOMP(ML,EL); RETURN(A);
  (*6*) END APFINT;
\end{verbatim}
}
\index{APFINT}
\verb/APCOMP/ denotes the composition of an 
exponent and the fraction part of a floating point number.
\verb/ILOG2/ means the integer logarithm base 2, 
\verb/IDP2/ denotes `integer division by power of 2' and
\verb/IMP2/ denotes `integer multiplication by power of 2'.
All three algorithms exploit the $\beta$ representation of
integers and the fact, that $\beta$ is itself a power of 2.
\verb/ISUM/ denotes integer sum.
\verb/APPR2/ means the number $z$ of
binary digits of the representation.

{\footnotesize
\begin{verbatim}
  PROCEDURE APSUM(A,B: LIST): LIST;
  (*Arbitrary precision floating point sum.
  A, B and C are arbitrary precision floating point numbers.
  C is the sum of A and B. C=A+B.*)
  VAR   C, EL, EL1, EL2, ML, ML1, ML2: LIST;
  BEGIN
  (*1*) (*A or B zero.*) 
        ML1:=APMANT(A); ML2:=APMANT(B); 
        IF ML1 = 0 THEN RETURN(B) END;
        IF ML2 = 0 THEN RETURN(A) END;
  (*2*) (*check exponent range.*) 
        EL1:=APEXPT(A); EL2:=APEXPT(B); 
        EL:=MASABS(EL1-EL2);
        IF EL > APPR2 THEN 
           IF EL1 > EL2 THEN RETURN(A) ELSE RETURN(B) END;
           END;
  (*3*) (*normalize mantisa and add.*) 
        EL:=IMIN(EL1,EL2); 
        ML1:=IMP2(ML1,EL1-EL); ML2:=IMP2(ML2,EL2-EL);
        ML:=ISUM(ML1,ML2); C:=APFINT(ML);
  (*4*) (*shift.*) EL:=EL-APPR2; C:=APSHFT(C,EL);
  (*5*) (*finish.*) RETURN(C);
  (*6*) END APSUM;
\end{verbatim}
}
\verb/APEXPT/ and \verb/APMANT/ extract the exponent 
and the fraction part (mantissa) of a floating point number.
\verb/MASABS/ determines the absolute value of the argument.
\verb/IMP2/, \verb/IMIN/ and \verb/ISUM/ denote 
integer multiplication by power of 2, integer minimum and integer sum 
respectively.
\verb/APSHFT/ adds the second parameter to the
exponent of the floating point number 
and checks the exponent for overflow or underflow.
\index{overflow}\index{underflow}


\subsection{Exercises}

\begin{enumerate}
\item Let $\bf R$ denote the real numbers.
      Use Newtons method to
      write an algorithm to approximate a zero of 
      a function $f : {\bf R} \longrightarrow {\bf R}$
      up to a desired precision $\varepsilon >0$.
      With this algorithm compute a zero of the 
      function $f(x) = x^2 - 2$ 
      up to 50 decimal digits.
\end{enumerate}

The Newton iteration is defined as:
\begin{displaymath}
       x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)}, 
       \ \mbox{ for } \ x_n \in {\bf R}, \ n \in \N.
\end{displaymath}

Recall the properties of the Newton iteration:

{\bf Proposition:} Let 
$D = \lbrack a, b \rbrack \subset {\bf R}$ be a closed 
and bounded interval in the real numbers
and let $f : D \longrightarrow {\bf R}$ 
be a two times continuous differentiable function on $D$ with
\begin{enumerate}
\item $f(a) \cdot f(b) < 0$, 
\item $f'(\xi) \neq 0$ for all $\xi \in D$,
\item $f''(\xi) \geq 0$ or
      $f''(\xi) \leq 0$ for all $\xi \in D$.
\end{enumerate}
If further $x_1 \in D$, 
then the Newton sequence
$\{ x_n \}_{n \in {\bf N}}$
converges for all $x_0 \in (a,b)$ monotonous 
against the unique zero $\xi$ of $f$.

With the conditions of the proposition we obtain 
three terminating conditions:
\begin{enumerate}
\item If $n$ is greater than a maximal allowable number of iterations, 
      then condition 1) is not fulfilled in the 
      neighbourhood of $x_0$, i.e.
      there is possibly no zero near $x_0$. 
\item If $f'(x_n) < \varepsilon$, 
      then condition 2) is not fulfilled
      i.e. there is possibly a singularity near $x_n$.
\item $\vert x_{n+1} - x_n \vert < \varepsilon$ 
      i.e. $\vert \frac{f(x_n)}{f'(x_n)} \vert < \varepsilon$. 
      Then $x_{n+1}$ is an approximation for $\xi$.
\end{enumerate}

With this information the algorithm can be formulated 
as follows: 
\begin{verbatim}
  dig:=50. APSPRE(dig). 
  AbsErr:=APFRN(RNRED(1,IEXP(10,dig/2))).
  MaxIter:=100.

  PROCEDURE Newton(f,fp,x);
  (*Newton iteration. f and fp are functions.
  x is the starting value for iteration. A fix point
  of x-f(x)/fp(x) is returned. *)
  VAR   i, y, z, zp, w: ANY;
  BEGIN 
  (*1*) i:=0; y:=x;
  (*2*) WHILE i < MaxIter DO i:=i+1;
              z:=f(y); zp:=fp(y);
              IF APCMPR(APABS(zp),AbsErr) <= 0 THEN
                 CLOUT("Derivation becommes zero."); 
                 BLINES(1); RETURN(y) END;
              w:=APQ(z,zp); y:=APDIFF(y,w);
              IF APCMPR(APABS(z),AbsErr) <= 0 THEN
                 RETURN(y) END;
              END;
        CLOUT("Maximal number of iterations reached."); 
        BLINES(1); RETURN(y);
  (*9*) END Newton. 
\end{verbatim}
The maximal allowed number of iterations is set to 100
(variable \verb/MaxIter/).
The absolute error is to be no greater than $10^{-50}$
(variable \verb/AbsErr/).
If one of the terminating conditions 1) or 2) is reached, 
a message is printed and the computation is stopped. 
Otherwise the algorithm terminates by condition 3) and returns 
an approximation of the zero of $f$.

The function $f(x) = x^2 - 2$ with derivation $f'(x) = 2 x$ 
can be formulated as algorithm as follows:
\begin{verbatim}
  zwei:=APFINT(2).

  PROCEDURE E(x);
  (*Expression function. An expression is evaluated at x. *)
  VAR   y: ANY;
  BEGIN 
  (*1*) (* x**2 - 2 *)
        y:=APEXP(x,2); y:=APDIFF(y,zwei);
        RETURN(y);
  (*9*) END E. 

  PROCEDURE Ep(x);
  (*Expression function derivation. The derivation of
  an expression is evaluated at x. *)
  VAR   y: ANY;
  BEGIN 
  (*1*) (* 2 x *)
        y:=APPROD(x,zwei);
        RETURN(y);
  (*9*) END Ep. 
\end{verbatim}

A sample output follows:
\begin{verbatim}
  start:=APFINT(1).
  {0 sec} ANS: (1 (0 0 0 0 0 134217728))

  b:=Newton(E,Ep,start).
  {6 sec} ANS: (1 (202854696 513744239 228305493 18243426 
                   133414089 189812531))

  BEGIN CLOUT("AbsErr = "); APWRIT(AbsErr); BLINES(0); 
        CLOUT("Result = "); APWRIT(b); BLINES(0); 
        CLOUT("W2     = "); APWRIT(APROOT(zwei,2)); 
        BLINES(0) END. 
 
  AbsErr = 0.100000000000000000000000000000000000
             000000000000000E-24
 
  Result = 0.141421356237309504880168872420969807
             856967187537694E1

  W2     = 0.141421356237309504880168872420969807
             856967187537694E1
\end{verbatim}
First the starting point for the iteration is set to 1.
Then the function \verb/Newton/ is called with 
the function \verb/E/, its derivation \verb/Ep/
and the starting point as input.
The computation needs 6 seconds on an Atari ST. 
Finally the absolute error, the zero and
for comparison the square root of 2 are printed.
