% 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}{1}

\section{Rational Number Arithmetic}

The elements of $\Q$,
fractions of integers are in the following 
called {\bf rational numbers}. 
We will first discuss the representation of 
rational numbers by lists.

{\bf Note:} 
Let $a \in \Q$, $a = \frac{p}{q}$, $p, q \in \Z$, then there
exist integers $p', q' \in \Z$,
with $q' > 0$ and $\mbox{\rm gcd}(p',q') = 1$ such that:
\begin{displaymath}
       \frac{p}{q} = \frac{p'}{q'}.
\end{displaymath}
$p$ and $p'$ are called denominator and 
$q$ and $q'$ are called numerator of the 
rational number $a$.  

{\bf Definition:} List representation of rational numbers.
\begin{quote}
       $0 \in \Q$ is represented by the atom $0$.
       \\
       $\frac{p}{q} \in \Q$, is represented 
       by the list $(p',q')$, where $p', q'$ are represented as 
       integers. $p', q'$ defined as before.  
\end{quote}
\index{list representation}\index{rational number representation}
\index{representation}

Example: 
\begin{quote}
    $\displaystyle\frac{7}{3}$ is represented as $(7,3)$. \\
    $\displaystyle-\frac{1}{2}$ is represented as $(-1,2)$. \\
    $\displaystyle\frac{0}{3}$ is represented as $0$. \\
    The representation of $\displaystyle\frac{\beta}{3}$ is $((0,1),3)$. \\
    $\displaystyle-\frac{\beta}{3}$ is represented as $((0,-1),3)$. \\
    $\displaystyle\frac{4}{8}$ is represented as $(1,2)$. 
\end{quote}


\subsection{Algorithms}

The programs of the most important rational number algorithms 
and their complexity are summarized in the following.

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 and 
$\R = \{ x \in \O: \ x$ represents an element of ${\rm \bf Q} \}$ 
be the set of rational numbers. 
\index{rational number algorithms}\index{rational number}
Further let $L(a)$ denote the maximum of the length 
of the numerator and denominator of $a$ 
($L(a) = \mbox{\rm max}\{ L(p'), L(q') \}$).
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}.
The methods for efficient product and sum algorithms are 
due to P. Henrici.
The time analyses are due to G. E. Collins.
\index{complexity}

\begin{deflist}{$c \gets RNPROD(a,b)$}
\item[$b \gets RNINT(a)$] $a \in \I$, $b \in \R$. 
     $b = \frac{a}{1}$ is the embedding of 
     the integer $a$ into the rational numbers. 
     Since the list $(a,1)$ is built
     $\tma = 2$, $\cma = 2$, $\tmi = 1$, $\cmi = 0$.
     \index{RNINT}
\item[$c \gets RNRED(a,b)$] $a, b \in \I$, $c \in \R$. 
     $c = \frac{a}{b}$ is the construction of a rational number
     from an integer numerator and a denominator.
     $a$ and $b$ are reduced to lowest terms.
     The list $(a',b')$ is built
     with $\frac{a'}{b'} = \frac{a}{b}$, $b' > 0$ 
     and ${\rm gcd}(a',b') = 1$.
     $\tma = \tma_{{\rm IGCD}} = L(c)^2$, $\cma = L(c)^2$, 
     $\tmi = 1$, $\cmi = 0$.
     \index{RNRED}
\item[$b \gets RNDEN(a)$] $a \in \R$, $b \in \I$. 
     $a = \frac{n}{b}$, $b$ is the denominator of $a$.
     $t = 1$, $c = 0$.
     \index{RNDEN}
\item[$b \gets RNNUM(a)$] $a \in \R$, $b \in \I$. 
     $a = \frac{b}{d}$, $b$ is the numerator of $a$.
     $t = 1$, $c = 0$.
     \index{RNNUM}
\item[$b \gets RNNEG(a)$] $a, b \in \R$. 
     $b = -a$ is the negative of $a$. 
     The sign of the denominator must be changed, so
     $\tma = \tma_{{\rm INEG}} = L(a)$, $\cma = L(a)$.
     \index{RNNEG}
\item[$s \gets RNSIGN(a)$] $a \in \R$, $s \in \{ -1, 0, 1 \}$. 
     $s$ is the sign of $a$. 
     The sign of the denominator must be determined, so
     $\tma = \tma_{{\rm ISIGN}} = L(a)$, $c = 0$.
     \index{RNSIGN}
\item[$b \gets RNABS(a)$] $a, b \in \R$. 
     $b = \vert a \vert$ is the absolute value of $a$. 
     If ${\rm sign}(a) = -1$ then $a$ must change the sign, so
     $\tma = L(a)$, $\tmi = 1$, $\cma = L(a)$, $\cmi = 0$.
     \index{RNABS}
\item[$s \gets RNCOMP(a,b)$] $a, b \in \R$, $s \in \{ -1, 0, 1 \}$. 
     $s = {\rm sign}(a-b)$ is the sign of $a-b$. 
     Let $a = \frac{a_1}{a_2}$, $b = \frac{b_1}{b_2}$,
     then $ a < b \ \Longleftrightarrow \ a_1 b_2 < b_1 a_2$.
     Therefore possibly integer products must be formed and
     the computing time is proportional to integer product and 
     comparison. 
     So if $L(a) = L(b)$ we have 
     $\tma = \tma_{{\rm IPROD}} + \tma_{{\rm ICOMP}} = L(a)^2$, 
     $\tmi = 2 \tmi_{{\rm ISIGN}} = 2$, $\cma = 2 L(a)$, $\cmi = 0$. 
     \index{RNCOMP}
\item[$c \gets RNPROD(a,b)$] $a, b, c \in \R$.
     $c = a \cdot b$ is the product of $a$ and $b$.
     Let $a = \frac{a_1}{a_2}$, $b = \frac{b_1}{b_2}$.
     The product, defined as 
     \begin{displaymath}
     c = \frac{c_1}{c_2} =
     \frac{a_1}{a_2} \cdot \frac{b_1}{b_2} =
     \frac{a_1 \cdot b_1}{a_2 \cdot b_2},
     \end{displaymath}
     is computed in a way that exploits the precondition
     that the denominator and numerator have gcd $=1$.
     Therefore let $d_1 = {\rm gcd}(a_1,b_2)$, 
     $d_2 = {\rm gcd}(a_2,b_1)$ and 
     let $a_1 = d_1 a'_1$, $b_2 = d_1 b'_2$,
     $b_1 = d_2 b'_1$ and $a_2 = d_2 a'_2$. 
     So  
     $\displaystyle c = \frac{a'_1 \cdot b'_1}{a'_2 \cdot b'_2}$,
     and we obtain the postcondition
     ${\rm gcd}(a'_1 b'_1, a'_2 b'_2) = 1$ without 
     actually computing that gcd.
     If $L(a) = L(b)$,
     the computing time is therefore only 
     $\tma = L(a)^2$ instead of $(2L(a))^2$ for the classical method.
     $\cma = L(a)^2$, $\tmi = 2$ and $\cmi = 2$.
     \index{RNPROD}
\item[$b \gets RNEXP(a,n)$] $a, b \in \R$, $n \in \N$.
     $c = a^n$ is the $n$--th power of $a$ (exponentiation).
     Like the integer exponentiation
     $c$ is computed by a binary exponentiation method.
     The computing time is proportional to 
     the time for the computation of the `biggest' product, so  
     $\tma = (n \cdot L(a))^2$, $\cma = 2 \cdot n \cdot L(a)$. 
     $\tmi = 2$ and $\cmi = 2$.
     \index{RNEXP}
\item[$b \gets RNINV(a)$] $a, b \in \R$.
     $b = 1 / a$ is the inverse of $a$. 
     If $a = \frac{a_1}{a_2}$ then $1/a = \frac{a_2}{a_1}$.
     Only if the denominator has negative sign, the 
     signs of the denominator and numerator must be changed.     
     $\tma = 2 \tma_{{\rm INEG}} = 2 L(a)$, 
     $\cma = 2 \cma_{{\rm INEG}} = 2 L(a)$, 
     $\tmi = 2$ and $\cmi = 2$. 
     \index{RNINV}
\item[$c \gets RNQ(a,b)$] $a, b, c \in \R$.
     $c = a / b$ is the quotient of $a$ and $b$.
     The inverse of $b$ is determined and the product 
     of $a$ and $1/b$ is computed.     
     So the computing time is
     $\tma = \tma_{{\rm RNINV}} + \tma_{{\rm RNPROD}} = L(a)^2$. 
     $\cma = L(a)^2$, $\tmi = 4$ and $\cmi = 4$. 
     \index{RNQ}
\item[$c \gets RNSUM(a,b)$] $a, b, c \in \R$.
     $c = a + b$ is the sum of $a$ and $b$. 
     Let $a = \frac{a_1}{a_2}$, $b = \frac{b_1}{b_2}$.
     The sum is defined as 
     \begin{displaymath}
     c = \frac{c_1}{c_2} =
     \frac{a_1}{a_2} + \frac{b_1}{b_2} =
     \frac{a_1 \cdot b_2 + a_2 \cdot b_1}{a_2 \cdot b_2}.
     \end{displaymath}
     We will also exploit the preconditions 
     that the denominator and numerator have gcd $=1$
     to minimize the computing time.
     Therefore let $d = {\rm gcd}(a_2,b_2)$ 
     and let $a_2 = d a'_2$, $b_2 = d b'_2$. 
     Further let $t = a_1 b_2 + a_2 b_1$, 
     $t' = a_1 b'_2 + a'_2 b_1$ and
     $e = {\rm gcd}(t',d)$.
     Now observe that 
     \begin{displaymath}
     {\rm gcd}(t,a_2 b_2) =
     d \cdot {\rm gcd}(t', a_2 b'_2) =
     d \cdot {\rm gcd}(t', d) = d \cdot e.
     \end{displaymath}
     Since $d$ divides $a_1 b_2 + a_2 b_1$ and
     $a_2 b_2$ the first equation holds.
     And since both $a'_2$ and $b'_2$ have gcd $=1$ with
     $a_1 b'_2 + a'_2 b_1$, the second equation holds.
     Let $t' = t'' e$ and $a_2 = a''_2 e$ then
     the sum is 
     $\displaystyle c = \frac{t''}{a''_2 \cdot b'_2}$.
     The postcondition ${\rm gcd}(t'', a''_2 b'_2) = 1$ holds
     by construction of $t''$ and $a''_2$.
     If $L(a) = L(b)$
     the computing time is 
     $\tma = \tma_{{\rm IGCD}_d} 
            + 2 \tma_{{\rm IPROD}_{t'}} + \tma_{{\rm ISUM}_{t'}} 
            + \tma_{{\rm IGCD}_e}$.
     $\tma = L(a) ( L(a) - L(d) + 1 ) 
             + 2 L(a) ( L(a) - L(d) + 1 ) + 2 L(a)
             + 2 L(a) ( L(d) - L(e) + 1 )$.
     For $L(d) = 1$ we obtain 
     $\tma = L(a)^2 + 2 L(a)^2 + 4 L(a) = 3 L(a)^2$
     and for $L(d) = L(a)$, 
     $\tma = L(a) + 4 L(a) + 2 L(a)^2 = 3 L(a)^2$.
     For the classical method we get 
     $\tma = 3 L(a)^2 + 2 L(a) + (2L(a))^2 = 7 L(a)^2$.
     Further $\cma = L(a)^2$, 
     $\tmi = {\rm const}$ and $\cmi = 2$.
     \index{RNSUM}
\item[$c \gets RNDIF(a,b)$] $a, b, c \in \R$.
     $c = a - b$ is the difference of $a$ and $b$. 
     $b$ is negated, then the sum is computed, so
     $\tmi = L(b) $, $\cmi = L(b) $. 
     The maximal computing time is proportional to 
     the maximal computing time of $RNSUM$, so 
     $\tma = {\rm max}\{ L(a), L(b) \}$, 
     $\cma = {\rm max}\{ L(a), L(b) \}$. 
     \index{RNDIF}
\item[$a \gets RNREAD()$] $a \in \R$.
     A rational number $a$ is read from the actual input stream.
     A conversion from decimal representation to 
     $\beta$ representation is done 
     and the numerator and denominator are reduced to lowest terms, 
     so
     $\tma = L(a)^2$ and $\cma = L(a)^2$. \\
     The syntax accepted by $RNREAD$ for rational numbers is:
\begin{verbatim}
rat = int [ "/" int ] 
\end{verbatim}
     \index{syntax}\index{rational number syntax}
     \index{RNREAD}
\item[$a \gets RNDRD()$] $a \in \R$.
     Same as $RNREAD$ except for a different syntax.
     The syntax accepted by $RNDRD$ for rational numbers is:
\begin{verbatim}
rat = int [ "/" int 
          | "." unsigned-int [ "E" beta-int ] ] 
\end{verbatim}
     \index{syntax}\index{rational number syntax}
     {\bf Note:} No blanks are allowed before \verb/"E"/.
     \index{RNDRD}
\item[$RNWRIT(a)$] $a \in \R$.
     The rational number $a$ is written to the actual output stream.
     A conversion from $\beta$ representation to 
     decimal representation is done, so
     $\tma = L(a)^2$ and $\cma = L(a)^2$.
     The syntax is the same as for $RNREAD$.
     \index{RNWRIT}
\item[$RNDWR(a,s)$] $a \in \R$, $s \in \A$.
     The rational number $a$ is written to the actual output stream.
     With $s$ digits following the decimal point.
     The syntax is:
\begin{verbatim}
rat = int "." unsigned-int [ "+" | "-" ] 
\end{verbatim}
     \index{syntax}\index{rational number syntax}
     A trailing \verb/"+"/ (or \verb/"-"/) indicates 
     whether the 
     rational number is greater (or smaller) than
     the written decimal approximation.
     \index{RNDWR}
\item[$a \gets RNRAND(n)$] $0 \leq n \in \A$, $a \in \R$.
     $a = \frac{a_1}{\vert a_2 \vert + 1}$ reduced to lowest terms 
     is a random rational number with $a_{1,2} = IRAND(n)$.
     $\tma = L(a)^2$ and $\cma = L(a)^2$.
     \index{RNRAND}
\end{deflist}

This concludes the summary of 
rational number arithmetic functions.

Examples:
\begin{verbatim}
      a:=RNRED(6,-8).      --> (-3,4)

      a:=RNREAD(). 3/4     --> (3,4)
      a:=RNREAD(). 3/-4    --> (-3,4)
      a:=RNDRD(). 3.4      --> (17,5)
      a:=RNDRD(). 3.14E7   --> (31400000,1)

      RNWRIT(a).           --> -3/4
      RNDWR(a,10).         --> -0.7500000000
      RNDWR(a,0).          --> -1.-
      RNDWR(a,1).          --> -0.7+
\end{verbatim}
The first statement shows the normalization of 
a rational number $\frac{6}{-8} = \frac{-3}{4}$ 
with ${\rm gcd}(3,4) = 1$ and $4 > 0$. 

In the next two statements \verb/RNREAD/ is used to 
read two rational numbers. Observe that \verb"3/-4" 
has negative numerator which is normalized during input.
\verb/RNDRD/ is able to read the decimal fraction
\verb/3.4/ which is $3 + \frac{4}{10}$
$= 3 + \frac{2}{5}$ $= \frac{15 + 2}{5}$ $=\frac{17}{5}$
as shown.
The number \verb/3.14E7/ is interpreted as 
$(3 + \frac{14}{100}) \cdot 10^7$, which gives the
rational number $\frac{31400000}{1}$. 

The output routine \verb/RNWRIT/ needs no further 
explanation. 
\verb/RNDWR/ writes a rational number as decimal fraction
with specified number of digits after the decimal point.
$\frac{-3}{4}$ with $10$ digits after the decimal point 
is exactly $-0.7500000000$.
With $0$ digits after the decimal point $-1.-$ is printed,
the trailing $-$ indicates that $-1. < - \frac{3}{4}$.
With $1$ digit after the decimal point $-0.7+$ is printed
which indicates that $-0.7 > - \frac{3}{4}$.

For illustration we list 
the algorithms \verb/RNSUM/ and \verb/RNPROD/ in Modula--2
in MAS.
The function of the algorithms should be clear from the 
step comments and the integer representation 
discussed before.

{\footnotesize
\begin{verbatim}
  PROCEDURE RNPROD(R,S: LIST): LIST;
  (*Rational number product.  R and S are rational numbers.  T=R*S.*)
  VAR   D1, D2, R1, R2, RB1, RB2, S1, S2, SB1, SB2, T, T1, T2: LIST;
  BEGIN
  (*1*) (*r=0 or s=0.*)
        IF (R = 0) OR (S = 0) THEN T:=0; RETURN(T); END;
  (*2*) (*obtain numerators and denominators.*) FIRST2(R,R1,R2);
        FIRST2(S,S1,S2);
  (*3*) (*r and s integers.*)
        IF (R2 = 1) AND (S2 = 1) THEN T1:=IPROD(R1,S1);
           T:=LIST2(T1,1); RETURN(T); END;
  (*4*) (*r or s an integer.*)
        IF R2 = 1 THEN IGCDCF(R1,S2,D1,RB1,SB2); T1:=IPROD(RB1,S1);
           T:=LIST2(T1,SB2); RETURN(T); END;
        IF S2 = 1 THEN IGCDCF(S1,R2,D2,SB1,RB2); T1:=IPROD(SB1,R1);
           T:=LIST2(T1,RB2); RETURN(T); END;
  (*5*) (*general case.*) IGCDCF(R1,S2,D1,RB1,SB2);
        IGCDCF(S1,R2,D2,SB1,RB2); T1:=IPROD(RB1,SB1); T2:=IPROD(RB2,SB2);
        T:=LIST2(T1,T2); RETURN(T);
  (*8*) END RNPROD;
\end{verbatim}
}
\index{RNPROD}
\verb/FIRST2/ accesses the first two elements of a list.
\verb/LIST2/ constructs a list of two elements.
\verb/IGCDCF/ computes the gcd (4--th (VAR) parameter)  
together with the cofactors (5-th and 6-th parameter).
\verb/IPROD/ is the product of two integers.
The correctness of step 5 is discussed in the summary.

{\footnotesize
\begin{verbatim}
  PROCEDURE RNSUM(R,S: LIST): LIST;
  (*Rational number sum.  R and S are rational numbers.  T=R+S.*)
  VAR   D, E, R1, R2, RB2, S1, S2, SB2, T, T1, T2: LIST;
  BEGIN
  (*1*) (*r=0 or s=0.*)
        IF R = 0 THEN T:=S; RETURN(T); END;
        IF S = 0 THEN T:=R; RETURN(T); END;
  (*2*) (*obtain numerators and denominators.*) FIRST2(R,R1,R2);
        FIRST2(S,S1,S2);
  (*3*) (*r and s integers.*)
        IF (R2 = 1) AND (S2 = 1) THEN T1:=ISUM(R1,S1);
           IF T1 = 0 THEN T:=0; ELSE T:=LIST2(T1,1); END;
           RETURN(T); END;
  (*4*) (*r or s an integer.*)
        IF R2 = 1 THEN T1:=IPROD(R1,S2); T1:=ISUM(T1,S1);
           T:=LIST2(T1,S2); RETURN(T); END;
        IF S2 = 1 THEN T1:=IPROD(R2,S1); T1:=ISUM(T1,R1);
           T:=LIST2(T1,R2); RETURN(T); END;
  (*5*) (*general case.*) IGCDCF(R2,S2,D,RB2,SB2);
        T1:=ISUM(IPROD(R1,SB2),IPROD(RB2,S1));
        IF T1 = 0 THEN T:=0; RETURN(T); END;
        IF D <> 1 THEN E:=IGCD(T1,D);
           IF E <> 1 THEN T1:=IQ(T1,E); R2:=IQ(R2,E); END;
           END;
        T2:=IPROD(R2,SB2); T:=LIST2(T1,T2); RETURN(T);
  (*8*) END RNSUM;
\end{verbatim}
}
\index{RNSUM}
\verb/ISUM/ denotes the sum of two integers.
\verb/IGCD/ denotes the integer gcd.
\verb/IQ/ is the integer quotient. The 
other algorithms are mentioned in the 
description of \verb/RNPROD/.
The correctness of step 5 is discussed in the summary.


\subsection{Exercises}

\begin{enumerate}
\item Write an algorithm to compute the 
      exponential series $\rm exp$ over the rational numbers
      up to a desired precision $\varepsilon >0$.
      With this algorithm compute $e = {\rm exp}(1)$ up to 50 
      decimal digits.
\end{enumerate}

The solution to the exercise is discussed in the sequel.

The exponential series is defined for complex $x$ by
\begin{displaymath}
      {\rm exp}(x) = \sum_{n=1}^{\infty} \frac{x^n}{n !}.
\end{displaymath}
\index{exponential series}
The exponential series can be approximated by
$\sum_{n=1}^{N} \frac{x^n}{n !} + r_{N+1}(x)$.
Where for the rest we have
\begin{displaymath}
      r_{N+1}(x) < 2 \frac{\vert x \vert^{N+1}}{(N+1) !}.
\end{displaymath}
\index{approximation}

Let $\varepsilon > 0$ be fixed. We want to approximate 
${\rm exp}(x)$ such that $r_{N+1}(x) < \varepsilon$, therefore the
summand must satisfy 
$\frac{\vert x \vert^{N+1}}{(N+1) !} \leq $
$\vert \frac{x^{N+1}}{(N+1) !} \vert < \frac{\varepsilon}{2}$.

With this information the algorithm can be formulated as follows:

\begin{verbatim}
  PROCEDURE Exp(x,eps);
  (*Exponential function. eps is the desired precision. *)
  VAR   s, xp, ep, i, y: ANY;
  BEGIN 
  (*1*) y:=RNINT(1); s:=RNINT(1); i:=0; 
        ep:=RNPROD(eps,RNRED(1,2));
  (*2*) REPEAT i:=i+1; xp:=RNRED(1,i);
               y:=RNPROD(y,x); y:=RNPROD(y,xp);
               s:=RNSUM(s,y)
               UNTIL RNCOMP(RNABS(y),ep) <= 0;
        RETURN(s)
  (*9*) END Exp.
\end{verbatim}
\index{Exp}
The complexity can be estimated as follows:
the most expensive operations in the REPEAT--loop
are \verb/RNPROD(y,x)/, \verb/RNSUM(s,y)/ and 
\verb/RNCOMP( . ,ep)/, which have 
computing times proportional to $L(.)^2$. 
For the `biggest' product $x^{n-1} \cdot x$
we have $\tma_{\rm RNPROD} = (n L(x)) L(x)$. 
For the `biggest' sum 
$(\sum_{i=1}^{n-1} \frac{x^i}{i !}) + \frac{x^n}{n !}$ 
we have $\tma_{\rm RNSUM} = (n L(x))^2$. 
The comparison needs also 
$\tma_{\rm RNCOMP} = (n L(x))^2$.
By this the computing time for the exponential series is 
$\tma_{\rm Exp} = (n L(x))^2$.

As an example we are going to compute $e = {\rm Exp}(1)$
with precision $\varepsilon = \frac{1}{10^{50}}$.
The sample output follows:
\begin{verbatim}
  dig:=50.   Eps:=RNRED(1,IEXP(10,dig)).

  one:=RNINT(1).

  e:=Exp(one,Eps).
  {20 sec} ANS: ((119769761 450433631 444044040 360650700 
                 406458113 17125896) (0338539520 159342123 
                 356614372 176392732 6300265))

  BEGIN CLOUT("AbsErr = "); RNDWR(Eps,dig); BLINES(0);     
        CLOUT("Result = "); RNDWR(e,dig); BLINES(0);
        CLOUT("Result = "); RNWRIT(e); BLINES(0) END. 
 
  AbsErr = 0.000000000000000000000000000000000
             00000000000000001
 
  Result = 2.718281828459045235360287471352662
             49775724709369996-
 
  Result = 76384051975228859737656454938414688
           9815927382313633/281001223550575979
           708628521248902313987276800000000
\end{verbatim}
The computation needs $20$ seconds on an Atari ST.
Then the absolute error, 
$e$ as decimal fraction and $e$ as rational number 
are printed. 
Observe that $L(e) = 6$ by counting the $\beta$--integers
from the internal representation of $e$.
