%+-----------------------------------------------------------------------------+
%|                                                                             |
%|                   Entiers de longueur arbitraire                            |
%|                                                                             |
%+-----------------------------------------------------------------------------+

% M. Quercia, 24/08/2001

\documentclass[a4paper]{report}
\input accents.tex
%\usepackage[T1]{fontenc}
\usepackage{amssymb}

\def\Numerix{{\tt Numerix}}
\def\Clong{{\tt Clong}}
\def\Dlong{{\tt Dlong}}
\def\Slong{{\tt Slong}}
\def\GMP{{\tt GMP}}
\def\Big{{\tt Big\_int}}

\def\ra{\rightarrow}
\def\la{\leftarrow}

\def\sv{\vskip4mm}

\font\sltt = cmsltt10
{\catcode`(=\active\catcode`/=\active\catcode`*=\active
\gdef\startpar{%
  \def\à{\accent 18 a}
  \def\é{\accent 19 e}
  \def\è{\accent 18 e}
   \def\ra{$\rightarrow$}
  \def\la{$\leftarrow$}
  \def\eq{$=$}
  \def\neq{$\ne$}
  \def\lt{$<$}
  \def\le{$\leqslant$}
  \def\gt{$>$}
  \def\ge{$\geqslant$}
 \catcode`(=\active\catcode`*=\active
  \def({\futurelet\next\suitepar}
  \def*{\futurelet\next\suiteast}
  \def\suitepar{\char40\relax\ifx\next*\bgroup\sltt\fi}
  \def\suiteast{\char42\relax\ifx\next)\egroup\fi}
}%
\gdef\startslash{%
  \def\à{\accent 18 a}
  \def\é{\accent 19 e}
  \def\è{\accent 18 e}
  \def\ra{$\rightarrow$}
  \def\la{$\leftarrow$}
  \def\eq{$=$}
  \def\neq{$\ne$}
  \def\lt{$<$}
  \def\le{$\leqslant$}
  \def\gt{$>$}
  \def\ge{$\geqslant$}
  \catcode`/=\active\catcode`*=\active
  \def/{\futurelet\next\suitepar}
  \def*{\futurelet\next\suiteast}
  \def\suitepar{\char47\relax\ifx\next*\bgroup\sltt\fi}
  \def\suiteast{\char42\relax\ifx\next/\egroup\fi}
}}

\newenvironment{camllisting}
{\bgroup\startpar\catcode`§=0\advance\hsize by 5cm}
{\egroup}
\newenvironment{clisting}
{\bgroup\startslash\catcode`§=0\advance\hsize by 5cm}
{\egroup}
\newenvironment{shelllisting}
{\bgroup\catcode`§=0\advance\hsize by 5cm}
{\egroup}

\title{\Huge\bf Numerix\vspace{1cm}\\Big integer library}
\author{Michel Quercia\\
\tt michel.quercia\char 64 prepas.org\vspace{5mm}\\
}
\date{version 0.19, August 24, 2001}

\begin{document}
\maketitle
\setcounter{tocdepth}1
\tableofcontents

                         %+----------------+
                         %|  Présentation  |
                         %+----------------+

\chapter{Presentation}

\Numerix\ is a library implementing arbitrary long signed integers
and the usual arithmetic operations between those numbers.
Designed for a use with the Ob\-jec\-tive-Caml language, it is also available
with reduced functionalities for the
Camllight, C and Pascal  languages on 32 or 64 bit Unix-type computers.
It is shipped in three different versions:

\begin{description}
\item\Clong:\par
written in standard C. The basic object is a ``digit'',
the length of which is half of a machine word.
So, elementary operations giving a two digit result
are implemented with ordinary C operations on {\tt long} variables,
and this library should be portable to every computer with a binary
arithmetic and words of even bit-length not fewer than 32 bits.

\item\Dlong:\par
also written in C, but a digit is a whole machine word.
Operations between digits are handled with the datatype
{\tt long long} (a {\tt gcc} feature) which for now restricts this
library to 32 bit computers (on the 64 bit computers at the
Inria, a {\tt long long} is of the same size as a
{\tt long} and there are no double-precision operations).

\item\Slong:\par
written partly in assembly language for
Intel x86 processors and partly in C, a digit is a 32 bit word.
\end{description}

Concerning the speed, \Numerix\ compares well to the other
multi-precision libraries commonly available, especially
\Big\ (the adaptation of {\tt BigNum} for Camllight/Ocaml) and \GMP.
Below are the computing times for the $n$ first decimal digits
of~$\pi$ on a Linux PC with an Athlon-650Mhz processor and a
128Mb random access memory:
\sv
\begin{center}
\begin{tabular}{|r|r|r|r|r|r|}
\hline
$n$      &\Slong    &\Dlong     &\Clong     &\tt GMP-3 &\Big \\
\hline
$10^4$   &  0.06s   &    0.24s  &    0.33s  &    0.08s &   0.45s\vphantom{$2^{2^{2}}$}\\
$10^5$   &  1.49s   &    6.49s  &    9.05s  &    4.95s &  57.22s\\
$10^6$   & 36.27s   &  148.71s  &  208.61s  &  505.58s &  15867s \\
\hline
\end{tabular}
\end{center}
\sv
The same algorithm is used in the five cases, derived from a series expansion
from Ramanujan, and only the big integer implementation differs.
The libraries \Slong, \Clong, \Dlong\ and \GMP\ were used with a main
program in C, whereas \Big\ was with a main program in Ocaml.
However, the influence of the main language on the running time is 
negligible for this kind of program for which the main part of the computing
time is spent with the operations on several-million-bit-long numbers;
the running times are similar when all the libraries are used with an Ocaml
main program.
\sv
Below are the computing times
on a Dec workstation with an alpha-500 processor and a 256Mb memory~:
\sv
\begin{center}
\begin{tabular}{|r|r|r|}
\hline
$n$      &\Clong  &\Big \\
\hline               
$10^4$   & 0.15s  & 0.55s\vphantom{$2^{2^{2}}$}\\
$10^5$   & 4.68s  &   60s\\
$10^6$   &  112s  & 8310s\\
\hline
\end{tabular}
\end{center}
\sv

This high computing speed comes from the implementation of fast algorithms
for all operations,
namely multiplication (Karatsuba and Sch\"onage (FFT) algorithms),
division (Burnikel-Ziegler algorithm),
square root (Zimmermann algorithm),
gcd (recursive Lehmer algorithm)
and binary to decimal conversion. {\tt GMP-3.1} provides similar
algorithms for multiplication and division achieving a greater speed than \Numerix\
on those operations for operands below one million bits long, and a smaller
speed for operands above one million bits.
But the other operations are implemented by quadratic algorithms
resulting in a greater computing time with \GMP\
than with \Numerix\ for an ``average'' program.
Moreover, \GMP\ and Camllight/Ocaml each have their own memory manager
and this duality results in some circumstances in an important
slow-down or even a memory exhaust causing the program to be aborted.
Concerning \Big, all operations starting from multiplication
have a quadratic or higher complexity, therefore this library is not well
suited for computation with huge numbers.
\sv

On the other hand,
for computations involving only ``small'' numbers (say with with fewer than
300 bits), \Numerix\ also performs nicely compared to \Big\
because of a lower memory management overhead, and the handling at the C or
assembly level of signs and integer lengths instead of handling them
at the Caml/Ocaml level.
\GMP, though having fine-tuned algorithms for small size operands,
is generally slower than \Numerix\ when driven by a Caml/Ocaml main program
because of the double memory management problem.
The Hamming problem (to find the $n^{\hbox{\small th}}$ natural integer having
only 2 and 3 and 5 as prime divisors) involves roughly
$n^{1/3}\ln(n)$
operations with small integers, from 100 to 300 bits.
Below are the computing times for each of the libraries linked with an
Ocaml main program (on a Linux PC Athlon-650, 128Mb RAM):
\sv
\begin{center}
\begin{tabular}{|r|r|r|r|r|r|}
\multispan6 \hfil with Ocaml 2.04\hfil\\
\noalign{\smallskip}
\hline
$n$      & \Slong   & \Dlong    & \Clong    & \tt GMP-3 & \Big \\
\hline
$10^{12}$&   0.17s   &    0.28s &   0.26s    &    2.13s &   0.69s\vphantom{$2^{2^{2}}$}\\
$10^{15}$&   1.51s   &    2.52s &   2.44s    &   20.23s &   6.80s \\
$10^{18}$&  17.06s   &   29.07s &  28.99s    &  233.62s &  79.59s \\
$10^{21}$& 214.33s   &  355.56s & 370.77s    & 2815.57s & 891.14s \\
\hline
\noalign{\medskip}
\multispan6 \hfil with Ocaml 3.00\hfil\\
\noalign{\smallskip}
\hline
$n$      & \Slong   & \Dlong    & \Clong    & \tt GMP-3 & \Big \\
\hline
$10^{12}$&   0.17s   &    0.27s &   0.26s    &    2.54s &   0.70s\vphantom{$2^{2^{2}}$}\\
$10^{15}$&   1.47s   &    2.61s &   2.57s    &       -- &   6.58s \\
$10^{18}$&  17.05s   &   30.10s &  30.77s    &       -- &  75.52s \\
$10^{21}$& 213.15s   &  368.21s & 386.83s    &       -- & 933.48s \\
\hline
\end{tabular}
\end{center}
\sv
{\tt GMP-3} does not pass this test with $n\geqslant 10^{15}$ and Ocaml-3.00
because of a memory overflow.
\sv

Though designed to be interfaced with the functional
Camllight and Ocaml  languages,
\Numerix\ allows ``in-place operations'',
that is to say reusing the memory already allocated to some variable for storing the
result of an operation instead of allocating a new memory block for
this result. If the memory block allocated to a variable is too short
for storing a result then a new large enough block is allocated to this variable
and the former is given back to the Camllight/Ocaml memory manager
for a potential recycling. The size increase follows
a ``double the need'' policy (allocate a block twice as large as necessary)
in order to avoid a ceaseless reallocation.
In-place computation with this policy lowers to almost zero the memory
management overhead and its influence on the total execution time, the cost
being a less intuitive programming style and a greater memory use.
Below are the running times for the Hamming problem with the in-place
computation:
\sv
\begin{center}
\begin{tabular}{|r|r|r|r|r|r|}
\multispan6 \hfil with Ocaml 2.04\hfil\\
\noalign{\smallskip}
\hline
$n$      & \Slong   & \Dlong    & \Clong    &\tt GMP-3 & \Big \\
\hline
$10^{12}$&   0.15s  &  0.27s    &   0.26s   &   0.85s   &   0.69s\vphantom{$2^{2^{2}}$}\\
$10^{15}$&   1.33s  &  2.39s    &   2.26s   &   3.24s   &   6.74s \\
$10^{18}$&  15.20s  & 27.35s    &  26.31s   &  23.10s   &  78.77s \\
$10^{21}$& 187.06s  &334.55s    & 330.44s   & 285.82s   & 978.26s \\
\hline
\noalign{\medskip}
\multispan6 \hfil with Ocaml 3.00\hfil\\
\noalign{\smallskip}
\hline
$n$      & \Slong   & \Dlong    & \Clong    &\tt GMP-3 & \Big \\
\hline
$10^{12}$&   0.17s  &  0.28s    &   0.27s   &   0.94s   &   0.76s\vphantom{$2^{2^{2}}$}\\
$10^{15}$&   1.38s  &  2.58s    &   2.36s   &   3.49s   &   7.51s \\
$10^{18}$&  15.46s  & 29.56s    &  27.30s   &  22.96s   &  87.15s \\
$10^{21}$& 189.25s  &360.63s    & 343.15s   & 284.75s   &1074.41s \\
\hline
\end{tabular}
\end{center}
\sv

In this test \Big\ is at a disadvantage because in-place operations
are not available and they have been simulated by using references
at the cost of a greater running time compared to the functional version.
On the other hand, \GMP\ performs better with in-place computations
as the two-memory-managers problem vanishes.


                    %+--------------------------+
                    %|  Utilisation avec Ocaml  |
                    %+--------------------------+

\chapter{Use with Ocaml}

\section{Interface}

\Numerix\ was developed and tested with Ocaml-2.02 and then Ocaml-3.00.
A few tests with other versions of Ocaml have not shown any
problem except for Ocaml-1.05 with which the automatic activation
of the pretty-printers in the toplevel {\tt ocamlnumx} could not be implemented
(manual activation with {\tt install\_printer} works, though).
Therefore, \Numerix\ is likely to run with any version of Ocaml
between 1.05 and 3.02 inclusive.
\sv

The five libraries \Clong, \Dlong, \Slong, \GMP\ and \Big\ are declared
as sub-modules of the module \Numerix\ with the same signature of type
{\tt Int\_type} in which the data types for big integers and mutable
big integers (for in-place operations) are abstract. This allows the
programmer to write a library-independent code and test his code with
any of the big integer implementations and without the need to recompile
the program, thanks to the module system of Ocaml
and to the possibility of defining parametric modules (functors).
You will find the public interface, part of the file {\tt numerix.mli}, below:
\sv

\halign{\hskip\leftskip\tt val #\hfil&\tt: #\hfil&\it(* # \hfil\it*)\cr
\multispan3\hskip\leftskip\tt module type Int\_type = sig\hfil\cr
\multispan3\hskip\leftskip\tt type t\phantom{ref} \it(* abstract integer \phantom{mutable} *)\hfil\cr
\multispan3\hskip\leftskip\tt type tref \it(* abstract mutable integer *)\hfil\cr
\noalign{\sv}
%
\multispan3\hskip\leftskip\it (* a,b,c,... denote the arguments of functions in this order *)\hfil\cr
\multispan3\hskip\leftskip\it(* unary and binary operations *)\hfil\cr
add          &t $\ra$ t $\ra$ t           &$a + b                $\cr
sub          &t $\ra$ t $\ra$ t           &$a - b                $\cr
mul          &t $\ra$ t $\ra$ t           &$a * b                $\cr
quo          &t $\ra$ t $\ra$ t           &$a$ div $b            $\cr
modulo       &t $\ra$ t $\ra$ t           &$a$ mod $b            $\cr
quomod       &t $\ra$ t $\ra$ t*t         &$(a$ div $b, a$ mod $b)$\cr
abs          &t $\ra$         t           &$|a|                  $\cr
neg          &t $\ra$         t           &$-a                   $\cr
sqr          &t $\ra$         t           &$a^2                  $\cr
sqrt         &t $\ra$         t           &$\lfloor\sqrt a\rfloor$\cr
powmod       &t $\ra$ t $\ra$ t $\ra$ t   &$a^b$ mod $c$, $b\geqslant0$\cr
gcd          &t $\ra$ t $\ra$ t           &gcd$(a,b)             $\cr
gcd\_ex      &t $\ra$ t $\ra$ t*t*t       &Bézout coefficients and gcd\cr
cfrac        &t $\ra$ t $\ra$ t*t*t*t*t   &\omit\it(* reduced integers, Bézout coef. and gcd *)\hidewidth\cr
eq           &t $\ra$ t $\ra$ bool        &$a =  b$ ?             \cr
neq          &t $\ra$ t $\ra$ bool        &$a \ne b$ ?            \cr
inf          &t $\ra$ t $\ra$ bool        &$a <  b$ ?             \cr
infeq        &t $\ra$ t $\ra$ bool        &$a \leqslant b$ ?      \cr
sup          &t $\ra$ t $\ra$ bool        &$a >  b$ ?             \cr
supeq        &t $\ra$ t $\ra$ bool        &$a \geqslant b$ ?      \cr
sgn          &t $\ra$         int         &sign$\rlap{$(a)$}\phantom{(a-b)}$ $(1,-1,0)$\cr
cmp          &t $\ra$ t $\ra$ int         &sign$(a-b)$ $(1,-1,0)$\cr
max          &t $\ra$ t $\ra$ t           &max$(a,b)             $\cr
min          &t $\ra$ t $\ra$ t           &min$(a,b)             $\cr
\noalign{\sv}
%
\multispan3\hskip\leftskip\it(* mixed operations *)\hfil\cr
add\_1       &t $\ra$ int $\ra$ t         &$a + b                 $\cr
sub\_1       &t $\ra$ int $\ra$ t         &$a - b                 $\cr
mul\_1       &t $\ra$ int $\ra$ t         &$a * b                 $\cr
quo\_1       &t $\ra$ int $\ra$ t         &$a$ div $b             $\cr
mod\_1       &t $\ra$ int $\ra$ int       &$a$ mod $b             $\cr
quomod\_1    &t $\ra$ int $\ra$ t*int     &$(a$ div $b, a$ mod $b)$\cr
eq\_1        &t $\ra$ int $\ra$ bool      &$a =  b$ ?              \cr
neq\_1       &t $\ra$ int $\ra$ bool      &$a \ne b$ ?             \cr
inf\_1       &t $\ra$ int $\ra$ bool      &$a <  b$ ?              \cr
infeq\_1     &t $\ra$ int $\ra$ bool      &$a \leqslant b$ ?       \cr
sup\_1       &t $\ra$ int $\ra$ bool      &$a >  b$ ?              \cr
supeq\_1     &t $\ra$ int $\ra$ bool      &$a \geqslant b$ ?       \cr
cmp\_1       &t $\ra$ int $\ra$ int       &sign$(a-b)$ $(1,-1,0)$ \cr
pow          &t $\ra$ int $\ra$ t         &$a ^ b                 $\cr
root         &t $\ra$ int $\ra$ t         &$\lfloor\root b \of a\rfloor$\cr
fact         &int $\ra$ t                 &$a!                    $\cr
random\_bits &int $\ra$ t                 &pseudo-random number \cr
\noalign{\sv}
%
\multispan3\hskip\leftskip\it(* access to binary representation *)\hfil\cr
nbits        &t $\ra$ int                 &bit size of $|a|$ \cr
lowbits      &t $\ra$ int                 &bits $0..30$ of $|a|$   \cr
highbits     &t $\ra$ int                 &bits $n-31..n-1$, $n=$nbits$(a)$\cr
nth\_bit     &t $\ra$ int $\ra$ bool      &bit $b$ of $|a|$        \cr
nth\_word    &t $\ra$ int $\ra$ int       &bits $16b..16b+15$ of $|a|$\cr
shr          &t $\ra$ int $\ra$ t         &sgn$(a)*(|a|$ div $2^b)$\cr
shl          &t $\ra$ int $\ra$ t         &$a * 2^b$               \cr
split        &t $\ra$ int $\ra$ t*t       &sgn$(a)*(|a|$ div $2^b, |a|$ mod $2^b)$\cr
join         &t $\ra$ t $\ra$ int $\ra$ t &$a + b*2^c$             \cr
\noalign{\sv}
%
\multispan3\hskip\leftskip\it(* conversion functions *)\hfil\cr
of\_int      &int    $\ra$ t       \cr
of\_string   &string $\ra$ t       \cr
int\_of      &t      $\ra$ int     \cr
string\_of   &t      $\ra$ string  \cr
\noalign{\sv}
%
\multispan3\hskip\leftskip\it(* in-place operations *)\hfil\cr
add\_in      &tref $\ra$ t $\ra$ t $\ra$ unit    &$a \la b + c                 $\cr
sub\_in      &tref $\ra$ t $\ra$ t $\ra$ unit    &$a \la b - c                 $\cr
mul\_in      &tref $\ra$ t $\ra$ t $\ra$ unit    &$a \la b * c                 $\cr
quo\_in      &tref $\ra$ t $\ra$ t $\ra$ unit    &$a \la b$ div $c             $\cr
quomod\_in   &tref $\ra$ tref $\ra$ t $\ra$ t $\ra$ unit &division and remainder\cr
abs\_in      &tref $\ra$ t $\ra$ unit            &$a \la |b|                   $\cr
neg\_in      &tref $\ra$ t $\ra$ unit            &$a \la -b                    $\cr
sqr\_in      &tref $\ra$ t $\ra$ unit            &$a \la b^2                   $\cr
sqrt\_in     &tref $\ra$ t $\ra$ unit            &$a \la \lfloor\sqrt b\rfloor $\cr
powmod\_in   &tref $\ra$ t $\ra$ t $\ra$ t $\ra$ unit &$a \la b^c \bmod d$, $c\geqslant0$\cr
add\_1\_in   &tref $\ra$ t $\ra$ int $\ra$ unit  &$a \la b + c                 $\cr
sub\_1\_in   &tref $\ra$ t $\ra$ int $\ra$ unit  &$a \la b - c                 $\cr
mul\_1\_in   &tref $\ra$ t $\ra$ int $\ra$ unit  &$a \la b * c                 $\cr
quomod\_1\_in&tref $\ra$ t $\ra$ int $\ra$ int   &$a \la b$ div $c$, returns $b$ mod $c$\cr
pow\_in      &tref $\ra$ t $\ra$ int $\ra$ unit  &$a \la b ^ c                 $\cr
root\_in     &tref $\ra$ t $\ra$ int $\ra$ unit  &$a \la \lfloor\root c \of b\rfloor$\cr
fact\_in     &tref $\ra$ int $\ra$ unit          &$a \la b!                    $\cr
shl\_in      &tref $\ra$ t $\ra$ int $\ra$ unit  &$a \la b$ shl $c             $\cr
shr\_in      &tref $\ra$ t $\ra$ int $\ra$ unit  &$a \la b$ shr $c             $\cr
split\_in    &tref$\ra$tref$\ra$t$\ra$int$\ra$unit &$(a,b) \la c$ split $d$     \cr
join\_in     &tref $\ra$ t $\ra$ t $\ra$ int $\ra$ unit&$a \la b + c*2^d$       \cr
gcd\_in      &tref $\ra$ t $\ra$ t $\ra$ unit    &$a \la$ pgcd$(b,c)$           \cr
gcd\_ex\_in  &tref$\ra$tref$\ra$tref$\ra$t$\ra$t$\ra$unit &Bézout coef. and gcd\cr
cfrac\_in    &tref $\ra$ tref $\ra$ tref $\ra$ tref $\ra$ tref $\ra$ t $\ra$ t $\ra$ unit\hidewidth\cr
\multispan3\hskip\leftskip\hfil\it(* reduced integers, Bézout coef. and gcd *)\cr
\noalign{\sv}
%
\multispan3\hskip\leftskip\it(* reference handling *)\hfil\cr
make\_ref    &t    $\ra$ tref                    &ref(copy $a$)\cr
copy\_in     &tref $\ra$ t $\ra$ unit            &$a \la b$    \cr
copy\_out    &tref $\ra$ t                       &copy($!a$)   \cr
look         &tref $\ra$ t                       &$!a$         \cr
\noalign{\sv}
%
\multispan3\hskip\leftskip\it(* miscellaneous *)\hfil\cr
name            &unit -> string   &name of module\cr
\multispan2\hskip\leftskip\tt val toplevel\_print : t $\ra$ unit  &printing with {\tt Format}\cr
\noalign{\sv}
\multispan3\hskip\leftskip\tt end \it(* module type Int\_type *)\hfil\cr
\noalign{\sv}
%
%
\multispan3\hskip\leftskip\it\hfil(* infix notation *)\hfil\cr
\noalign{\sv}
\multispan3\hskip\leftskip\tt module Infixes(E : Int\_type) : sig\hfil\cr
\omit\hskip\leftskip\tt  open E\cr
\noalign{\sv}
(  +  )  &   t $\ra$ t   $\ra$ t      & add      \cr
(  -  )  &   t $\ra$ t   $\ra$ t      & sub      \cr
(  *  )  &   t $\ra$ t   $\ra$ t      & mul      \cr
(  /  )  &   t $\ra$ t   $\ra$ t      & quo      \cr
(  \% )  &   t $\ra$ t   $\ra$ t      & modulo   \cr
( /\% )  &   t $\ra$ t   $\ra$ t*t    & quomod   \cr
( <{}< ) &   t $\ra$ int $\ra$ t      & shl      \cr
( >{}> ) &   t $\ra$ int $\ra$ t      & shr      \cr
(  ** )  &   t $\ra$ int $\ra$ t      & pow      \cr
\noalign{\sv}
(  +. )  &   t $\ra$ int $\ra$ t      & add\_1   \cr
(  -. )  &   t $\ra$ int $\ra$ t      & sub\_1   \cr
(  *. )  &   t $\ra$ int $\ra$ t      & mul\_1   \cr
(  /. )  &   t $\ra$ int $\ra$ t      & quo\_1   \cr
(  \%.)  &   t $\ra$ int $\ra$ int    & mod\_1   \cr
( /\%.)  &   t $\ra$ int $\ra$ t*int  & quomod\_1\cr
\noalign{\sv}
(  +! )  & int $\ra$ int $\ra$ int    & add      \cr
(  -! )  & int $\ra$ int $\ra$ int    & sub      \cr
(  *! )  & int $\ra$ int $\ra$ int    & mul      \cr
(  /! )  & int $\ra$ int $\ra$ int    & quo      \cr
(  \%!)  & int $\ra$ int $\ra$ int    & mod      \cr
\noalign{\sv}
(  =  )  &   t $\ra$ t   $\ra$ bool   & eq    (Ocaml $<$ 3.00)   \cr
( <>  )  &   t $\ra$ t   $\ra$ bool   & neq   (Ocaml $<$ 3.00)   \cr
(  <  )  &   t $\ra$ t   $\ra$ bool   & inf   (Ocaml $<$ 3.00)   \cr
( <=  )  &   t $\ra$ t   $\ra$ bool   & infeq (Ocaml $<$ 3.00)   \cr
(  >  )  &   t $\ra$ t   $\ra$ bool   & sup   (Ocaml $<$ 3.00)   \cr
( >=  )  &   t $\ra$ t   $\ra$ bool   & supeq (Ocaml $<$ 3.00)   \cr
\noalign{\sv}
(  =. )  &   t $\ra$ int $\ra$ bool   & eq\_1    \cr
( <>. )  &   t $\ra$ int $\ra$ bool   & neq\_1   \cr
(  <. )  &   t $\ra$ int $\ra$ bool   & inf\_1   \cr
( <=. )  &   t $\ra$ int $\ra$ bool   & infeq\_1 \cr
(  >. )  &   t $\ra$ int $\ra$ bool   & sup\_1   \cr
( >=. )  &   t $\ra$ int $\ra$ bool   & supeq\_1 \cr
\noalign{\sv}
(  =! )  & 'a  $\ra$ 'a  $\ra$ bool   & eq       \cr
( <>! )  & 'a  $\ra$ 'a  $\ra$ bool   & neq      \cr
(  <! )  & 'a  $\ra$ 'a  $\ra$ bool   & inf      \cr
( <=! )  & 'a  $\ra$ 'a  $\ra$ bool   & infeq    \cr
(  >! )  & 'a  $\ra$ 'a  $\ra$ bool   & sup      \cr
( >=! )  & 'a  $\ra$ 'a  $\ra$ bool   & supeq    \cr
\noalign{\sv}
( \~\ )    & tref $\ra$ t             & look (Ocaml $<$ 3.00)    \cr
( \~{}\~\ )& tref $\ra$ t             & look     \cr
\noalign{\sv}
\multispan3\hskip\leftskip\tt end \it(* Infixes functor *)\hfil\cr
%
%
\multispan3\hskip\leftskip\it\hfil(* available modules *)\hfil\cr
\noalign{\sv}
\omit\hskip\leftskip\tt module Big   &Int\_type        &Ocaml bigints\cr
\omit\hskip\leftskip\tt module Slong &Int\_type        &assembly longints\cr
\omit\hskip\leftskip\tt module Clong &Int\_type        &C longints\cr
\omit\hskip\leftskip\tt module Dlong &Int\_type        &C longints with double precision\cr
\omit\hskip\leftskip\tt module Gmp   &Int\_type        &GMP bigints\cr
%
\noalign{\sv}
\multispan3\hskip\leftskip\it\hfil(* timing and run-time selection of a module *)\hfil\cr
\noalign{\sv}
\multispan3\hskip\leftskip\tt   external chrono : string $\ra$ unit = "chrono"\hfil\cr
\noalign{\sv}
\multispan3\hskip\leftskip\tt   module type Main\_type = sig\hfil\cr
\multispan3\hskip\leftskip\tt   \quad  val main : string list $\ra$ unit\hfil\cr
\multispan3\hskip\leftskip\tt   end\hfil\cr
\multispan3\hskip\leftskip\tt   module Start(Main : functor(E : Int\_type) $\ra$ Main\_type) : sig\hfil\cr
\multispan3\hskip\leftskip\tt   \quad  val start : unit $\ra$ unit\hfil\cr
\multispan3\hskip\leftskip\tt   end\hfil\cr
}
\sv

                         %+-----------------+
                         %|  Détails Ocaml  |
                         %+-----------------+

\section{Details}

Modules {\tt Big}, {\tt Slong}, {\tt Clong}, {\tt Dlong} or {\tt Gmp}
are available only on those computers for which the hardware allows compilation
and also, concerning {\tt Big} and {\tt Gmp}, if the {\tt BigNum}
and {\GMP} libraries are installed.
As a rule, all modules of type {\tt Int\_type} are
interchangeable, that is to say any given operation with
valid arguments returns a result
semantically independent of the module used and of the machine word size.
The only exceptions are the {\tt gcd\_ex}, {\tt gcd\_ex\_in},
{\tt cfrac}, {\tt cfrac\_in}, {\tt look} operations and the
hash, serialize and deserialize functions (see below).
On the contrary, the exceptions raised in case of invalid arguments
may differ between modules.
\sv

%-------------------------------------------------------- Division
\subsubsection{Division}
Division operations {\tt quo}, {\tt quo\_1}, {\tt modulo}, {\tt mod\_1},
{\tt quomod} and {\tt quomod\_1}
and their in-place counterparts follow the rule:

\begin{description}

\item{\tt quomod} $a$ $b$ and {\tt quomod\_1} $a$ $b$
return the pair $(q,r)$ such that
$a = bq+r$ with $0\leqslant |r| < |b|$, $r$ having same sign as~$b$.
$b$ may not be zero.

\item{\tt quo} $a$ $b$ and {\tt quo\_1} $a$ $b$ return only~$q$.

\item{\tt modulo} $a$ $b$ and {\tt mod\_1} $a$ $b$ return only~$r$.
\end{description}
\sv


%------------------------------------------------------------ PGCD
\subsubsection{Gcd}
The operations related to the greatest common divisor are
{\tt gcd}, {\tt gcd\_ex}, {\tt cfrac} and their in-place counterparts.
\begin{description}

\item{\tt cfrac} $a$ $b$ returns a tuple $(p,q,u,v,d)$ such that:
\begin{enumerate}
\item$d$ is the positive gcd of $a$ and $b$;
\item$ua-vb = d$;
\item$pu - qv = 1$;
\item$pa = qb$ is the lcm of $a$ and $b$ with same sign as $ab$.
\end{enumerate}
The above conditions ensure uniqueness of $p,q,d$ when $a$ or $b$ is non null,
but the Bézout coefficients $u$ and $v$ are not unique and may differ
between modules. Ensuring their uniqueness is possible
as $p$ and $q$ are known, but it would have involved additional
potentially time-expensive divisions.

\item{\tt gcd\_ex} $a$ $b$ returns the triple $(u,v,d)$.
\item{\tt gcd} $a$ $b$ returns $d$.

\end{description}
\sv

%--------------------------------------------------------------- cmp,sgn
\subsubsection{Comparisons}
The {\tt sgn}, {\tt cmp} and {\tt cmp\_1} functions always return
one of the $0$, $1$ or $-1$ integers so it is possible to filter
the result of any of those functions using the {\tt match} construct.
\sv

The infix comparison symbols
({\tt <}, {\tt <=}, {\tt =}, {\tt <>}, {\tt >=} and {\tt >})
have a different status depending in which Ocaml version is used
and on the opening or non opening of a module built with the {\tt Infixes} functor.
\sv
\begin{itemize}
\item
With Ocaml versions lower than 3.00, if no
{\tt Infixes(E)} is opened, the {\tt <},\dots,{\tt >} symbols
denote the usual Ocaml polymorphic comparison operators,
of type \verb?'a->'a->bool?. These operators raise an
\sv\verb?Invalid_argument("equal: abstract value")?\sv\noindent
exception when called with big integers.

\sv\item
With Ocaml versions lower than 3.00, if an
{\tt Infixes(E)} module is opened, the {\tt <},\dots,{\tt >} symbols
denote the big integer comparison operators, of type
\verb?E.t->E.t?. The polymorphic comparison operators
remain available with the {\tt <!},\dots,{\tt >!} symbols.

\sv\item
Starting with Ocaml 3.00, the {\tt <},\dots,{\tt >} symbols denote
the usual Ocaml polymorphic comparison operators,
regardless of a possible opening of an {\tt Infixes(E)} module,
they are no more redefined by the {\tt Infixes} functor.
The {\tt Clong}, {\tt Dlong}, {\tt Slong} and {\tt Gmp} modules
provide an interface with the generic comparison function of Ocaml,
and the polymorphic comparison operators can be used with big integers
from these modules without raising an exception. Moreover, big integers
from these modules can be stored into ordered structures such as
the sets from the {\tt Set} module or the association tables from
the {\tt Map} module with the {\tt compare} generic comparison function.

\sv
On the contrary, the {\tt Bignum} library does not provide an interface
with the generic comparison function, therefore the polymorphic
comparison functions of Ocaml cannot be used with data of type
{\tt Big.t}. If one wishes to compare such data with the
{\tt <},\dots,{\tt >} infix symbols, one needs to redefine these symbols
on his own, or to modify the {\tt Bignum} library in order to
include an interface with the generic comparison function of Ocaml.
Such a modification is described in the {\bf Installation} chapter,
section {\bf Modifying the Bignum library}, page~\pageref{modif-bignum}.
\sv
Last, the {\tt <!},\dots,{\tt >!} symbols remain binded to the
polymorphic comparison operators by the {\tt Infixes} functor,
in order to preserve the compatibility with the previous \Numerix\ versions.
\end{itemize}
\sv

%-------------------------------------------------------------- repr. binaire
\subsubsection{Binary representation}
Functions giving access to the binary representation of big integers
follow the rules:

\begin{description}

\item{\tt nbits} $a$ returns the number of significant bits of $|a|$;
{\tt nbits} $0 = 0$.

\item{\tt lowbits} $a$ and {\tt highbits} $a$ return the $31$ lowest
or highest bits of $|a|$ if $a$ is non null and return $0$ if
$a=0$. For {\tt highbits}, when $0 < |a| < 2^{30}$, null bits
are pushed at the right end in order to get a $31$ bits word with highest
bit set.
Mathematically speaking, for $a\ne0$ and $n$ integer such that
$2^{n-1}\leqslant |a| < 2^n$:
\sv
\indent{\tt highbits}$(a) = (|a|*2^{\max(0,31-n)}) \hbox{ div } 2^{\max(n-31,0)}$.
\sv

\item{\tt nth\_bit} $a$ $n$ and {\tt nth\_word} $a$ $n$ return the $n^{\hbox{\small th}}$
bit or the $n^{\hbox{\small th}}$ $16$ bits word of $|a|$, with least significant
bit or word having index zero.
When $n$ is negative or greater than the length of~$|a|$
those functions return $0$.

\item{\tt shl} $a$ $n$ returns $a*2^n$ if $n\geqslant 0$ and
{\tt sgn}$(a)*(|a|$ div $2^{-n})$
if $n < 0$. {\tt shr} $a$ $n$ is equivalent to {\tt shl} $a$ $(-n)$.

\item{\tt split} $a$ $n$ splits $|a|$ into two parts and attaches the sign of $a$
to each. $n$ may not be negative.

\item{\tt join} $a$ $b$ $n$ returns the number $a + b*2^n$ even if
$a$ and $b$ have different signs or overlap.
$n$ may not be negative.
\end{description}
\sv

%-------------------------------------------------------------------- nb. aléatoires
\subsubsection{Pseudo-random integers}
{\tt random\_bits} $n$ returns a pseudo-random integer between
$0$ and $2^n-1$ inclusive, $n$ may not be negative.
The pseudo-random generator used is the Ocaml one, so the numbers
returned by {\tt random\_bits} are identical for all runs of the same
program not modifying the random generator seed, and are identical
for all \Numerix\ big integer modules available.

%-------------------------------------------------------------------- références
\subsubsection{Mutable integers}
Type {\tt tref} values behave semantically as references to
type {\tt t} values, but their implementation
may be more efficient and remains abstract.

\begin{description}
\item {\it op\tt\_in $r$ \it args} computes {\it op args} and stores
the result in the memory referenced by~$r$. If the result does not fit
in the memory available, then a new block is allocated
for storing the result and $r$ is updated in order to reference this new block.
For operations returning tuples: {\tt quomod}, {\tt gcd\_ex},
{\tt cfrac} and {\tt split} the in-place counterpart stores the components
of the tuple in the memory blocks referenced by the first arguments.
Those references must be distinct.

\item{\tt make\_ref} $v$ performs a physical copy of $v$ and returns
a reference to this copy.

\item{\tt copy\_in} $r$ $v$ performs a physical copy of $v$ in the memory block
referenced by~$r$.

\item{\tt copy\_out} $r$ returns a physical copy of the memory referenced
by~$r$.

\item{\tt look} $r$ returns the value referenced by~$r$. The result
is volatile, that is to say it is guaranteed to be valid only
until next in-place operation involving~$r$.
Read-modify-write operations, for instance
{\it op\tt\_in} $r$ $({\tt look}\ r)$ $x$, are handled correctly.
The {\tt Infixes} functor defines two abbreviations for {\tt look}:
{\tt\~{}} valid for all version of Ocaml up to 2.99 and
{\tt\~{}\~{}} valid for all version of Ocaml up to 3.00 ({\tt\~{}} became a
reserved word with Ocaml 3.00).
\end{description}
\sv

%--------------------------------------------------------------- Chrono
\subsubsection{Timing}
{\tt chrono \it msg} prints on the standard error stream
the CPU time in seconds since the beginning of the process, the
difference with the previous time and the {\it msg} string.
The inclusion of a few calls to {\tt chrono} within a program
informs the user of the approximate running
times of the various phases in this program.
\sv

%--------------------------------------------------------------- Start
\subsubsection{Run-time selection of a module}
\label{selmodule}
The {\tt Start} functor allows the user to select a particular
implementation of big integers at run-time  and to execute the
program with this implementation. The argument of {\tt Start} is a
{\tt Main} functor receiving an implementation of the big integers  as an argument
and returning an implementation for the
\hbox{\tt main:string list $\ra$ unit}  function which constitutes the actual
entry point of the program.
The argument of {\tt main} is the list of command-line parameters
except those specifying which implementation of big integers
to use. The choice of a particular implementation
is done in the {\tt start}  function which parses
the command-line, searching for a {\tt -e \it module} option
where {\it module} is the lower-case name of a big integer module available.
When several {\tt -e \it module} options are given on the
command-line, the last one prevails; when none is,
the first module available is selected as a default.
When an {\tt -e} option is not followed by a valid module
name, an error message is printed showing the list of available modules
and the program is aborted.
\sv

%--------------------------------------------------------------- hash, serialisation
\subsubsection{Hashing, serialization and deserialization}
Starting with Ocaml 3.00, the {\tt Clong}, {\tt Dlong}, {\tt Slong} and {\tt Gmp}
modules provide interfaces with the generic hashing function and with
the serialization and deserialization functions of Ocaml, therefore
the big integers from these modules
can be stored into hash tables using the {\tt Hashtbl.hash} function,
and can be exported or imported through the {\tt output\_value} and {\tt input\_value} functions.
The {\tt Bignum} library provides interfaces with the
serialization and deserialization functions of Ocaml, but no interface
with the generic hash function, so data of type
{\tt Big.t} can be exported or imported with the
{\tt output\_value} and {\tt input\_value} functions,
but they cannot be stored into hash tables using the
{\tt Hashtbl.hash} generic hash function. It is possible to modify the
{\tt Bignum} library so as to include an interface with the generic
hash function, please refer to chapter {\bf Installation}, section
{\bf Modifying the Bignum library}, page~\pageref{modif-bignum} for such a modification.
\sv
Concerning the {\tt Hashtbl.hash} generic hash function,
the hash keys returned by this function can differ between modules
for semantically equal big integers, due to
different binary representations.
\sv
Concerning the export/import of big integers
(functions {\tt output\_value} and {\tt input\_value}) and the encoding
of big integers as sequences of bytes (functions from the {\tt Marshal} module),
typing must be preserved between export or encoding and import or decoding,
that is to say it is not possible to turn a big integer from one
module into a big integer from another module with these functions.


                    %+---------------------------+
                    %|  Modules supplémentaires  |
                    %+---------------------------+

\section{Additional modules}

\Numerix\ provides two modules allowing one to make new modules
of type {\tt Int\_type} from existing modules:
{\tt Numcmp} and {\tt Numcount}.

%------------------------------------------------------------ Cmp
\subsection{{\tt Numcmp}: comparison between two modules}
The {\tt Numcmp} module contains two functors:

\begin{verbatim}
module M(A:Int_type)(B:Int_type) : Int_type

module Start(Main : functor(E:Int_type) -> Main_type) : sig
  val start : unit -> unit
end
\end{verbatim}

{\tt Numcmp.M} receives as arguments two modules $A$ and $B$ of type
{\tt Int\_type} and returns a module $C$ of the same type, in which each
{\it op\/} operation is done with calls to $A$.{\it op\/}
and  $B$.{\it op\/} followed by semantic comparison between the results.
When a comparison fails, that is to say when $A$.{\it op\/}
and $B$.{\it op\/} return semantically different results with supposed
semantically identical arguments, an exception is raised
and the arguments and results in each module are printed on
the standard error stream. This functor was used to debug the
under-development modules by comparison with a reliable one,
and except for this situation, its use is not recommended as duplication
of calculations and comparison of results are time-consuming.
Concerning operations {\tt gcd\_ex}, {\tt gcd\_ex\_in}, {\tt cfrac} and
{\tt cfrac\_in}, Bézout coefficients are not compared, those
from $B$ are translated into values of type $A.{\tt t}$ in order to
build results of type  $C.{\tt t}$.
\sv

{\tt Numcmp.Start} is a functor similar to {\tt Numerix.Start}
allowing one to choose at run-time which big integer modules to compare
through an {\tt -e \it mod1\_mod2} option.
The module pairs available are:
\sv
{\tt big\_clong}, {\tt big\_dlong}, {\tt big\_slong}, {\tt big\_gmp}

{\tt gmp\_clong}, {\tt gmp\_dlong}, {\tt gmp\_slong}.
\sv
There is no default pair. When an incorrect {\tt -e} option is given,
the program is aborted and the list of available module pairs
is printed on the standard error stream.

%--------------------------------------------------------------- Count
\subsection{{\tt Numcount}: counting operations}
The {\tt Numcount} module contains two functors :

\begin{camllisting}
\begin{verbatim}
module M(A:Int_type) : sig

  type statelt = {
    mutable n:float;  (* number of calls       *)
    mutable s:float;  (* sum of operand sizes  *)
    mutable m:int     (* maximal operand size  *)
  }

  val cadd  : statelt (* add      sub                              *)
  val cmul  : statelt (* mul      sqr                              *)
  val cquo  : statelt (* quo      modulo       quomod              *)
  val cpow  : statelt (* pow      powmod       fact                *)
  val croot : statelt (* sqrt     root                             *)
  val cgcd  : statelt (* gcd      gcd_ex       cfrac               *)
  val cbin  : statelt (* shr      shl          split       join    *)
                      (* nbits    lowbits      highbits    nth_bit *)
                      (* nth_word random_bits                      *)
  val cmisc : statelt (* abs      neg          make_ref    copy_in *)
                      (* copy_out comparisons  conversions         *)

  val clear_stats : unit -> unit (* reset stats             *)
  val print_stats : unit -> unit (* display stats on stderr *)

  module Int : Int_type (* big integer module *)
end

module Start(Main : functor(E:Int_type) -> Main_type) : sig
  val start : unit -> unit
end
\end{verbatim}
\end{camllisting}

The {\tt Numcount.M} functor receives as argument a module $A$
of type {\tt Int\_type} and returns a module $B${\tt.int} of the same type,
in which each {\it op\/} operation is done by calling $A$.{\it op\/}
and updating counter depending on~{\it op}. The purpose
of this functor is to provide statistics on the number of big integer
operations performed by a program. The big integer operations are merged
into eight categories each category being associated with a different counter:

\sv
\par {\tt nadd } counts additions and subtractions;
\par {\tt nmul } counts multiplications and squares;
\par {\tt nquo } counts divisions;
\par {\tt npow } counts exponentiations and factorials;
\par {\tt nroot} counts square roots and $p$-th roots;
\par {\tt ngcd } counts greatest common divisor and associated operations;
\par {\tt nbin } counts operations on the binary representations;
\par {\tt nmisc} counts all other operations.
\sv

\sv\noindent
Each counter $B${\tt.cxxx} has three fields:

\begin{description}
\item{$B${\tt.cxxx.n}}~: number of calls to one of the functions associated with {\tt cxxx}~;
\item{$B${\tt.cxxx.s}}~: sum of the bit sizes of the arguments for all calls~;
\item{$B${\tt.cxxx.m}}~: maximum the bit sizes of the arguments for all calls.
\end{description}

For each call to a function in $B${\tt.Int}, field {\tt n} of the
associated counter is increased by one, field {\tt s} is incremented
by the average bit size of big integer operands and field {\tt m} is
updated so as to hold the maximum bit size of an operand for any function
associated with this counter. Operands of type {\tt tref}, {\tt int}
or {\tt string} are not taken into account in size computations.
Please note that the operations done with $B${\tt.Int} are slower
than their counterpart in $A$ because of the counter updates and the
indirect calls overhead.
\sv

One can read the values of the counters and modify them at will, so as to
determine how many operations of each category have been performed since
the last reset.
The function $B${\tt.clear\_stats} resets all counters
and the function $B${\tt.print\_stats} displays on the standard error
stream the statistics relative to each counter (number of calls, average operand bit size,
maximum operand bit size).
\sv

{\tt Numcount.Start} is a functor similar to {\tt Numerix.Start}
allowing one to choose at run-time which big integer module $E$ to use
through an {\tt -e \it module} option with the same convention as for
{\tt Numerix.Start}. If the {\tt -count} option is given on the command line
then the function
\medskip

\centerline{\tt Main(Numcount.M$(E)$\tt.Int).main}

\medskip\noindent
is called with the list of remaining command line arguments and the
function {\tt Numcount.M}$(E)${\tt.print\_stats} is called at program
termination. If there is no {\tt -count} option then the function
{\tt Main}$(E)${\tt.main} is called as with {\tt Numerix.Start},
and no statistics is printed. In the second case, there is no slow-down
with respect to the use of {\tt Numerix.Start}.
\sv
Below is an example of the use or not use of the {\tt -count} option
with the program computing digits of~$\pi$ described in section
{\ref{pi}}:

\begin{verbatim}
exemples/pi/ocaml/pi-opt -e slong -count 1000000 -d -skip
    0.01     0.01 Count(Slong), surplace
    0.36     0.35 puiss 5
    3.79     3.43 sqrt
   26.48    22.69 série lb=6875847 ls=6875855
   31.93     5.45 quotient
   39.11     7.18 conversion
   op      count   avg.size   max.size
  add     424091        240    6875855
  mul     636133        323    6875847
  quo          3    2845643   10197784
  pow          3         13         19
 root          1    6643863    6643863
  gcd          0          -          -
  bin          1    4643867    4643867
 misc    1767125        353    6875855
3.
14159 26535  89793 23846  26433 83279  50288 41971  69399 37510
... (19998 lignes omises)
56787 96130  33116 46283  99634 64604  22090 10610  57794 58151

exemples/pi/ocaml/pi-opt -e slong 1000000 -d -skip
    0.00     0.00 Slong, surplace
    0.36     0.36 puiss 5
    3.83     3.47 sqrt
   23.96    20.13 série lb=6875847 ls=6875855
   29.41     5.45 quotient
   36.60     7.19 conversion
3.
14159 26535  89793 23846  26433 83279  50288 41971  69399 37510
... (19998 lignes omises)
56787 96130  33116 46283  99634 64604  22090 10610  57794 58151
\end{verbatim}
\sv

Computing the first million digits of~$\pi$ thus required
$424091$ additions/sub\-trac\-tions on operands having an average length
of $240$ bits, $636133$ multiplications/squares on operands having
an average length of $323$ bits, $3$ divisions between operands
having an average length of $2845643$, etc.
The time overhead for computing those statistics is approximately
$2.5$ seconds.


                          %+---------------+
                          %|  Compilation  |
                          %+---------------+

\section{Compilation}
Ocaml programs using \Numerix\ must be compiled with the following commands:
\sv
\begin{shelllisting}
\begin{verbatim}
ocamlc -custom§it options§tt nums.cma numerix.cma§it source files§tt \
       -cclib -lmlnumx -cclib -lnums -cclib -lgmp

ocamlopt§it options§tt nums.cmxa numerix.cmxa§it source files§tt \
       -cclib -lmlnumx -cclib -lnums -cclib -lgmp
\end{verbatim}
\end{shelllisting}
\sv


The {\tt nums.cma}, {\tt nums.cmxa}, {\tt numerix.cma} and
{\tt numerix.cmxa}  files contain
the Ocaml part of the {\tt BigNum} and \Numerix\ llibraries
in a compiled form
({\tt nums.cma} and {\tt nums.cmxa} are included in the Ocaml distribution).
You may need to add a {\tt -I \it path} option
in order to inform the compilers about the location of the
{\tt numerix.cma} and {\tt numerix.cmxa} files.
\sv

The {\tt -cclib -lmlnumx},  {\tt -cclib -lnums}
and {\tt -cclib -lgmp} options add the
{\tt libmlnumx.a}, {\tt libnums.a} and {\tt libgmp.a} files
to the list of libraries in which the linker searches for external functions.
{\tt libnums.a} contains, in a compiled form, the C part of {\tt BigNum},
{\tt libmlnumx.a} the C part of \Numerix\ and {\tt libgmp.a} the C part
of \GMP. You may need to add {\tt -ccopt -L\it path} options
in order to inform the linker about the location of
these {\tt libxxx.a} files.
If {\tt GMP} is not installed or if its interface with Ocaml is not
included in your \Numerix\ version, then the option {\tt -cclib -lgmp}
must be omitted. If the {\tt BigNum} library is not installed,
then the parameters {\tt nums.cmxa} and {\tt -cclib -lnums} must be
omitted.
\sv

Starting with Ocaml-3.00, the {\tt -custom}, {\tt -cclib -lxxx} and {\tt -ccopt xxx}
are recorded at build time into the {\tt numerix.cma} and {\tt numerix.cmxa}
files and don't need to be given on compile command lines for programs
using \Numerix..



                            %+-----------+
                            %|  Exemple  |
                            %+-----------+

\section{Example}

\begin{camllisting}
\begin{verbatim}
                (* +---------------------------------------------+
                   |  simple.ml file: Use of Numerix with Ocaml  |
                   +---------------------------------------------+ *)

(* computing (sqrt(3) + sqrt(2))/(sqrt(3)-sqrt(2)) with n digits *)

open Numerix

module Main(E:Int_type) = struct
  module I = Infixes(E)
  open E
  open I

  (* functional version *)
  let calc_func n =
    let ten_n  = (of_int(5) ** n) << n in   (* 10^n  *)
    let ten_2n = sqr(ten_n)            in   (* 10^2n *)
    let sqrt_2 = sqrt(ten_2n *. 200)   in   (* sqrt(2) with n+1 digits *)
    let sqrt_3 = sqrt(ten_2n *. 300)   in   (* sqrt(3) with n+1 digits *)
    (ten_n * (sqrt_3 + sqrt_2)) / (sqrt_3 - sqrt_2)

  (* in-place version *)
  let calc_in n =
    let ten_n  = make_ref(of_int 0) in
    let ten_2n = make_ref(of_int 0) in
    let sqrt_2 = make_ref(of_int 0) in
    let sqrt_3 = make_ref(of_int 0) in
    let x      = make_ref(of_int 0) in
    let y      = make_ref(of_int 0) in

    pow_in   ten_n    (of_int 5)  n;        (* ten_n <- 5^n ...      *)
    shl_in   ten_n    ~~ten_n     n;        (*        ... * 2^n      *)
    sqr_in   ten_2n   ~~ten_n;              (* ten_2n <- 10^(2n)     *)
    mul_1_in sqrt_2   ~~ten_2n    200;      (* sqrt_2 <- ...         *)
    sqrt_in  sqrt_2   ~~sqrt_2;             (* .. sqrt(2*10^(2n+2))  *)
    mul_1_in sqrt_3   ~~ten_2n    300;      (* sqrt_3 <- ...         *)
    sqrt_in  sqrt_3   ~~sqrt_3;             (* .. sqrt(3*10^(2n+2))  *)
    add_in   x        ~~sqrt_3    ~~sqrt_2; (* x <- sqrt_2 + sqrt_2  *)
    sub_in   y        ~~sqrt_3    ~~sqrt_2; (* y <- sqrt_3 - sqrt_2  *)
    mul_in   x        ~~ten_n     ~~x;      (* x <- trunc(10^n*x ... *)
    quo_in   x        ~~x         ~~y;      (*               ... /y) *)
    copy_out x                              (* result                *)

  (* main function *)
  let main arglist =

    let rec parse (n,f) = function
      | []          -> (n,  f)
      | "-test"::s  -> parse (30, calc_func) s
      | "-func"::s  -> parse (n,  calc_func) s
      | "-in"  ::s  -> parse (n,  calc_in)   s
      | "-n"::x::s  -> parse (int_of_string x, f) s
      | _ -> prerr_endline "syntax : simple [-e module] [-test] [-func|-in] [-n <n>]";
             exit(1)
    in
    let (n,f) = parse (30,calc_func) arglist in
    print_endline(string_of(f n))

end (* Main *)

module S = Numcount.Start(Main)
let _ = S.start()
\end{verbatim}
\end{camllisting}
\sv\noindent
Compilation and execution (with Ocaml 3.00):
\sv
\begin{verbatim}
> ocamlc -o simple-byte nums.cma numerix.cma simple.ml
> ./simple-byte -e slong
9898979485566356196394568149410
>
> ocamlopt -o simple-opt nums.cmxa numerix.cmxa simple.ml
> ./simple-opt -e gmp -n 50 -count
   op      count   avg.size   max.size
  add          2        170        171
  mul          4        250        333
  quo          1        253        338
  pow          1          3          3
 root          2        340        341
  gcd          0          -          -
  bin          1        117        117
 misc          2         85        170
989897948556635619639456814941178278393189496131335
\end{verbatim}

                      %+----------------------+
                      %|  Système interactif  |
                      %+----------------------+

\section{Customized toplevel}

{\tt ocamlnumx} is a customized toplevel derived from {\tt ocaml}
and linked against the {\tt numerix.cma} object file and the
{\tt libnums.a}, {\tt libmlnumx.a} and {\tt libgmp.a} static libraries.
It allows to use any
\Numerix\ module, the choice of a big integer implementation
being done through an appropriate {\tt open} directive.
\sv

\begin{verbatim}
> ocamlnumx
ocamlnumx : Objective Caml with big integer libraries
Numerix submodules : Big Clong Dlong Slong Gmp
Numerix version    : 0.19 (24 Aout 2001)
 
        Objective Caml version 3.02
                                                     
# open Numerix;;
# open Big;;
# fact(30);;
- : Numerix.Big.t = 265252859812191058636308480000000
# module I = Infixes(Big) open I;;
module I :
  sig
    val ( + ) : Numerix.Big.t -> Numerix.Big.t -> Numerix.Big.t
    val ( - ) : Numerix.Big.t -> Numerix.Big.t -> Numerix.Big.t
    val ( * ) : Numerix.Big.t -> Numerix.Big.t -> Numerix.Big.t
    ...
    val ( ~~ ) : Numerix.Big.tref -> Numerix.Big.t
  end
# (of_int 1) << 100;;
- : Numerix.Big.t = 1267650600228229401496703205376
# #quit;;
\end{verbatim}

                  %+------------------------------+
                  %|  Utilisation avec Camllight  |
                  %+------------------------------+

\chapter{Use with Camllight}

The Camllight interface for \Numerix\ is derived from
the Ocaml one by removing or adapting the functionalities specific
to the Ocaml language. Please refer to the previous chapter
to see the list of the available functions, only the differences with the
Ocaml version will be explained here.
This interface was successfully tested with Camllight versions
0.73, 0.74 and 0.75.

                            %+-----------+
                            %|  Modules  |
                            %+-----------+

\section{Modules}

Camllight's module system is rather limited and provides neither
sub-modules nor parametric modules.
Nevertheless, it is possible to write library-in\-de\-pen\-dent code
by using the short names of functions,
the long names being inferred by the compiler with the help of
{\tt\#open} directives included in the source file.
Doing this way, just modifying
those directives (possibly with a preprocessor)
and recompiling the source file will change the big integer implementation
used.
\sv

The available modules have the same names as in the Ocaml interface but
without initial capital letters:
{\tt big}, {\tt clong}, {\tt dlong}, {\tt slong} and {\tt gmp}.
There are no equivalents to the Ocaml modules built with the {\tt Numcmp.M} and
{\tt Numcount.M} functors.
Infix notations are available by opening the {\tt infxxx}  module
where {\tt xxx}
is the name of the module implementing big integers.


                           %+-------------+
                           %|  Fonctions  |
                           %+-------------+

\section{Functions}

All functions described in the Ocaml {\tt Int\_type} signature
have been interfaced to Camllight with only two differences:

\begin{description}
\item Division without remainder is named {\tt quo} in Ocaml but {\tt div}
in Camllight. The reason for this difference is the infix status of the
 {\tt quo} identifier in Camllight. The other names derived
from {\tt quo}: {\tt quomod}, {\tt quo\_1}, {\tt quomod\_1}, 
{\tt quo\_in}, {\tt quomod\_in} and {\tt quomod\_1\_in}
are unchanged.

\item Accessing the value held by a reference is written {\tt look} or {\tt \~{}}
in Ocaml, but {\tt look} or {\tt ?} in Camllight. There are two reasons
for this difference: the identifier {\tt ?} is reserved in Ocaml
and the identifier {\tt\~{}} has a prefix status in Ocaml,
but an infix one in Camllight.
\end{description}

                          %+---------------+
                          %|  Compilation  |
                          %+---------------+

\section{Compilation}
Caml programs using \Numerix\ must be compiled with the following command:
\sv
\begin{shelllisting}
\begin{verbatim}
camlc -custom§it options§tt nums.zo numerix.zo§it source files§tt -lclnumx -lnums -lgmp
\end{verbatim}
\end{shelllisting}
\sv
In their compiled form,
the {\tt nums.zo} and {\tt numerix.zo}  files contain
the Caml part of the libraries {\tt nums}  and \Numerix\
({\tt nums.zo} is included in the Camllight distribution).
You may need to add a {\tt -I \it path} option
in order to inform the compiler about the location of the
{\tt numerix.zo} file.
\sv

The {\tt -lclnumx},  {\tt -lnums}
and {\tt -lgmp} options add the
{\tt libclnumx.a}, {\tt lib\-nums.a} and {\tt libgmp.a} files
to the list of libraries in which the linker searches for external functions.
{\tt libnums.a} contains the C part of {\tt BigNum},
{\tt libclnumx.a} the C part of \Numerix\ and {\tt libgmp.a} the C part of
\GMP\  in a compiled form. You may need to add {\tt -ccopt -L\it path} options
in order to inform the linker about the location of
these files {\tt libxxx.a}.
If {\tt GMP} is not installed or if its interface with Camllight is not
included in your \Numerix\ version, then the {\tt -lgmp}  option
must be omitted.
Accordingly, if {\tt BigNum} is not installed, then the parameters
{\tt nums.zo} and {\tt -cclib -lnums} must be omitted.



                            %+-----------+
                            %|  Exemple  |
                            %+-----------+

\section{Example}

\begin{camllisting}
\begin{verbatim}
              (* +-------------------------------------------------+
                 |  simple.ml file: Use of Numerix with Camllight  |
                 +-------------------------------------------------+ *)

(* computing (sqrt(3) + sqrt(2))/(sqrt(3)-sqrt(2)) with n digits *)

#open "slong";;
#open "infslong";;

  (* functional version *)
  let calc_func n =
    let ten_n  = (of_int(5) ** n) << n in   (* 10^n  *)
    let ten_2n = sqr(ten_n)            in   (* 10^2n *)
    let sqrt_2 = sqrt(ten_2n *. 200)   in   (* sqrt(2) with n+1 digits *)
    let sqrt_3 = sqrt(ten_2n *. 300)   in   (* sqrt(3) with n+1 digits *)
    (ten_n * (sqrt_3 + sqrt_2)) / (sqrt_3 - sqrt_2);;

  (* in-place version *)
  let calc_in n =
    let ten_n  = make_ref(of_int 0) in
    let ten_2n = make_ref(of_int 0) in
    let sqrt_2 = make_ref(of_int 0) in
    let sqrt_3 = make_ref(of_int 0) in
    let x      = make_ref(of_int 0) in
    let y      = make_ref(of_int 0) in

    pow_in   ten_n    (of_int 5)  n;        (* ten_n <- 5^n ...      *)
    shl_in   ten_n    ?ten_n      n;        (*        ... * 2^n      *)
    sqr_in   ten_2n   ?ten_n;               (* ten_2n <- 10^(2n)     *)
    mul_1_in sqrt_2   ?ten_2n     200;      (* sqrt_2 <- ...         *)
    sqrt_in  sqrt_2   ?sqrt_2;              (* .. sqrt(2*10^(2n+2))  *)
    mul_1_in sqrt_3   ?ten_2n     300;      (* sqrt_3 <- ...         *)
    sqrt_in  sqrt_3   ?sqrt_3;              (* .. sqrt(3*10^(2n+2))  *)
    add_in   x        ?sqrt_3     ?sqrt_2;  (* x <- sqrt_3 + sqrt_2  *)
    sub_in   y        ?sqrt_3     ?sqrt_2;  (* y <- sqrt_3 - sqrt_2  *)
    mul_in   x        ?ten_n      ?x;       (* x <- trunc(10^n*x ... *)
    quo_in   x        ?x          ?y;       (*               ... /y) *)
    copy_out x;;                            (* result                *)

  (* main function *)
  let main arglist =

    let rec parse (n,f) = function
      | []          -> (n,  f)
      | "-test"::s  -> parse (30, calc_func) s
      | "-func"::s  -> parse (n,  calc_func) s
      | "-in"  ::s  -> parse (n,  calc_in)   s
      | "-n"::x::s  -> parse (int_of_string x, f) s
      | _ -> prerr_endline "syntax : simple [-test] [-func|-in] [-n <n>]";
             exit(1)
    in
    let (n,f) = parse (30,calc_func) arglist in
    print_endline(string_of(f n));
    flush stdout;;

main (tl(list_of_vect sys__command_line));;
\end{verbatim}
\end{camllisting}
\sv\noindent
Compilation and execution:
\sv
\begin{verbatim}
> camlc -custom -o simple nums.zo numerix.zo simple.ml \
        -lclnumx -lnums -lgmp
> ./simple
9898979485566356196394568149410
\end{verbatim}
\sv

Please note that all three {\tt libclnumx.a}, {\tt libnums.a}
and {\tt libgmp.a} libraries must be given to the linker though only the
{\tt slong} module  is actually used, because the other modules
are included in {\tt numerix.zo} and refer to functions from those
libraries.

                      %+----------------------+
                      %|  Système interactif  |
                      %+----------------------+

\section{Customized toplevel}

A customized toplevel is available as it was in the Ocaml version:
\sv

\begin{verbatim}
> camllight ~/lib/camlnumx
>       Caml Light version 0.74

camlnumx : Caml toplevel with big integer libraries
Numerix submodules : big clong dlong slong gmp
Numerix version    : 0.19 (24 Aout 2001)

##open "big";;
##open "infbig";;
#fact(30);;
- : t = 265252859812191058636308480000000
#(of_int 1) << 100;;
- : t = 1267650600228229401496703205376
#quit();;
\end{verbatim}

                       %+--------------------+
                       %|  Utilisation en C  |
                       %+--------------------+

\chapter{Use with C}

The C interface of \Numerix\ was derived from the Ocaml one
by adding a simple memory manager in order to cope with the lack of
Ocaml GC, and by restricting the interface to in-place operations.
The main purpose of this
interface is to allow a fair comparison between \Numerix\
and \GMP\ (designed to be used with C),
and to allow the compilation and the execution of test programs on computers
where Ocaml is not installed.
\sv

                           %+-------------+
                           %|  Interface  |
                           %+-------------+

\section{Interface}
The three {\tt clong}, {\tt dlong} and {\tt slong} modules  are
available, as far as the C compiler and the computer hardware
allow compilation.
The following {\tt \#define} directives must be given to specify
the size of a machine word and which module to use:

\begin{description}
\item{\tt \#define bits\_32} and {\tt \#define bits\_64} specify
the machine word size. One and only one of those directives must
be specified.
\item{\tt \#define use\_clong}, {\tt \#define use\_dlong} and
{\tt \#define use\_slong} select the module implementing big
integers. Not more than one of these directives may be specified, the
default module selected when none is specified is \Clong.
\end{description}

Those directives may be written at the beginning of each source file
or transmitted to the preprocessor with {\tt -Dxxx} options on the
compile command-line.
\sv

The file {\tt c-long\_int.h} defines the datatype {\tt xint} representing
a big integer and contains the prototypes for all the public functions dealing with
big integers. The function names are prefixed with a three character string
identifying the \Clong, \Dlong\ or \Slong\ module to which they belong
and the abstraction level at which they operate:

\begin{description}
\item{\tt cn\_nnn}: function {\tt nnn} from \Clong\  module operating on natural integers
(digit arrays);
\item{\tt cz\_nnn}: function {\tt nnn} from \Clong\ module operating on signed integers
(digit arrays with length and sign beside);
\item{\tt cx\_nnn}: function {\tt nnn} from \Clong\  module operating on big integers
(signed integers extensible and relocatable).
\item{\tt dn\_nnn}, {\tt dz\_nnn}, {\tt dx\_nnn}, same for \Dlong\ module.
\item{\tt sn\_nnn}, {\tt sz\_nnn}, {\tt sx\_nnn}, same for \Slong\ module.
\end{description}
\sv

Normally, the programmer should only care about
type {\tt xint} big integers, and use only {\tt cx\_nnn} or
{\tt dx\_nnn} or {\tt sx\_nnn} as functions operating on the big integers.
The operations at {\tt n} or {\tt z} level are for internal use only
and are not documented here. In order to allow writing
module-independent code, the
{\tt c-long\_int.h} file defines an {\tt xx} macro which has
{\tt cx\_} or {\tt dx\_} or {\tt sx\_} as expansion code depending on which symbol among
{\tt use\_clong}, {\tt use\_dlong} and {\tt use\_slong} is defined.
The recommended syntax to add {\tt a} and {\tt b} into {\tt x} is:
\sv
\indent{\tt xx(add)(\&x,a,b);}
\sv\noindent
this code being translated by the preprocessor into:
\sv
\indent{\tt cx\_add(\&x,a,b);} or {\tt dx\_add(\&x,a,b);} or {\tt sx\_add(\&x,a,b);}
\sv
The programmer is advised to systematically use the {\tt xx} macro, and
never to directly code the expanded identifiers. Then, 
just modifying the {\tt \#define use\_xxx} directive
will be the only change to do before a recompilation
with another big integer implementation.
Nevertheless,
the functions of one module cannot operate on the data of another
module, and there is no mechanism for distinguishing the {\tt xint} datatype
according to a specific module.
\sv

Below is a part of the file {\tt c-long\_int.h} showing the public
functions prototypes:

\begin{clisting}
\begin{verbatim}
/* public functions prefix  */
#if defined(use_slong)
#define xx(nom) sx_##nom
#elif defined(use_dlong)
#define xx(nom) dx_##nom
#else
#define xx(nom) cx_##nom
#endif

/* extensible integer */
typedef struct {...} * xint; 

/* allocation/deallocation */
xint xx(new)(void);
void xx(free)(xint *x);

/* initialization from a long, a big integer or a string */
xint xx(of_int)     (long a);
xint xx(of_xint)    (xint a);
xint xx(of_string)  (char *s);

/* modification of an integer already initialized */
void xx(copy)       (xint *x, xint a);              /* x §la a         */
void xx(copy_int)   (xint *x, long a);              /* x §la a         */
void xx(copy_string)(xint *x, char *s);             /* x §la val(s)    */
                                                    
/* usual operations */                          
void xx(add)   (xint *x, xint a, xint b);           /* x §la a+b       */
void xx(sub)   (xint *x, xint a, xint b);           /* x §la a-b       */
void xx(mul)   (xint *x, xint a, xint b);           /* x §la ab        */
void xx(quo)   (xint *x, xint a, xint b);           /* x §la a div b   */
void xx(quomod)(xint *x, xint *y,xint a, xint b);   /* x §la a div b, y §la a mod b */
void xx(gcd)   (xint *z, xint a, xint b);           /* x §la gcd(a,b)  */
void xx(powmod)(xint *x, xint a, xint b, xint c);   /* x §la a^b mod c */

/* extended gcd : z §la gcd(a,b), xa-by = z, xr-ys = 1 */
void xx(gcd_ex)(xint *x, xint *y, xint *z, xint a, xint b);
void xx(cfrac) (xint *r, xint *s, xint *x, xint *y, xint *z, xint a, xint b);

/* unary operations */
void xx(abs)   (xint *x, xint a);                   /* x §la |a|       */
void xx(neg)   (xint *x, xint a);                   /* x §la -a        */
void xx(sqr)   (xint *x, xint a);                   /* x §la a^2       */
void xx(sqrt)  (xint *x, xint a);                   /* x §la trunc(a^1/2) */
                                                    
/* mixed operations */                            
void xx(add_1) (xint *x, xint a, long b);           /* x §la a+b       */
void xx(sub_1) (xint *x, xint a, long b);           /* x §la a-b       */
void xx(mul_1) (xint *x, xint a, long b);           /* x §la ab        */
long xx(quomod_1) (xint *x, xint a, long b);        /* x §la a div b, returns a mod b */
void xx(shl)   (xint *x, xint a, long b);           /* x §la a*2^b     */
void xx(shr)   (xint *x, xint a, long b);           /* x §la a div 2^b */
void xx(split) (xint *x, xint *y,xint a, long b);   /* x §la a mod 2^b, y §la a div 2^b */
void xx(join)  (xint *x, xint a, xint b, long c);   /* x §la a + b*2^c */
void xx(pow)   (xint *x, xint a, long b);           /* x §la a^b       */
void xx(root)  (xint *x, xint a, long b);           /* x §la trunc(a^1/b) */
void xx(fact)  (xint *x, long a);                   /* x §la a!        */

/* comparison */
int xx(eq)     (xint a, xint b);                    /* a §eq b ?        */
int xx(neq)    (xint a, xint b);                    /* a §neq b ?        */
int xx(inf)    (xint a, xint b);                    /* a §lt b ?        */
int xx(infeq)  (xint a, xint b);                    /* a §le b ?        */
int xx(sup)    (xint a, xint b);                    /* a §gt b ?        */
int xx(supeq)  (xint a, xint b);                    /* a §ge b ?        */
int xx(cmp)    (xint a, xint b);                    /* sign(a-b)       */
int xx(sgn)    (xint a);                            /* sign(a)         */

int xx(eq_1)   (xint a, long b);                    /* a §eq b ?        */
int xx(neq_1)  (xint a, long b);                    /* a §neq b ?        */
int xx(inf_1)  (xint a, long b);                    /* a §lt b ?        */
int xx(infeq_1)(xint a, long b);                    /* a §le b ?        */
int xx(sup_1)  (xint a, long b);                    /* a §gt b ?        */
int xx(supeq_1)(xint a, long b);                    /* a §ge b ?        */
int xx(cmp_1)(xint a, long b);                      /* sign(a-b)       */

/* access to the binary representation, lowbits, highbits and int_of return
  31 bits only for compatibility with Ocaml */
long xx(nbits)   (xint a);                          /* size of a       */
long xx(lowbits) (xint a);                          /* see Ocaml       */
long xx(highbits)(xint a);                          /* see Ocaml       */
long xx(nth_word)(xint a, long n);                  /* bits 16b..16b+15*/
long xx(int_of)  (xint a);                          /* bits 0..30      */

/* conversion integer -> string, release the string with free_string */
char *xx(string_of)(xint a);
void xx(free_string)(char *s);

/* timing */
void chrono(char *msg);
\end{verbatim}
\end{clisting}

                          %+--------------+
                          %|  Précisions  |
                          %+--------------+

\section{Details}

A variable of {\tt xint}  type is a pointer to a data structure
handled by the \Numerix\ built-in memory manager.
The initialization of an {\tt x} variable of {\tt xint} type
is usually done in two steps:
\begin{enumerate}
\item initialization of the pointer {\tt x} with a call to {\tt xx(new)()};
\item assignment of a value by giving the address of {\tt x}, {\tt \&x},
as a result parameter for an operation, for instance {\tt xx(add)(\&x,a,b)}.
\end{enumerate}

The
{\tt xx(of\_int)}, {\tt xx(of\_xint)} and {\tt xx(of\_string)} functions  do
the initialization of the pointer and the assignment of a value
from an ordinary integer, another big integer or a string  in a single
step.
The instruction:
\sv
\indent{\tt xint x = xx(of\_int)($i$);}
\sv\noindent
is formally equivalent to the two instructions:
\sv
\indent{\tt xint x = xx(new)(); xx(copy\_int)(\&x,$i$);}
\sv\noindent
and similarly for {\tt xx(of\_xint)} and {\tt xx(of\_string)}.
The execution of an operation with a call such as:
\sv
\indent{\tt xx(quo)(\&x,a,b);}
\sv\noindent
is valid if and only if the following requirements are fulfilled:
\begin{enumerate}
\item the {\tt a} and {\tt b} variables are initialized and point to
valid values for that operation ({\tt a} points to any value
and {\tt b} points to a non zero value);
\item the {\tt x} variable contains an initialized pointer.
\end{enumerate}
\sv

It is not necessary for {\tt x} to point to some value before
this operation. If it does, then the memory block storing this value
will be overwritten with the result if the block is large enough,
otherwise a new memory block will be allocated to store the result, the
{\tt x} pointer will be directed towards this new block and the former one will
be deallocated.
\sv

Read-modify-write operations for which a same variable
is given as operand and result are handled correctly.
On the contrary, for operations returning several results
({\tt quomod}, {\tt gcd\_ex}, {\tt cfrac} and {\tt split}) a single variable
cannot be used for receiving more than one result.
For instance the following instruction is {\it not} allowed:
\sv
\indent{\tt xx(quomod)(\&x,\&x,a,b); /* \sltt illegal \tt */}
\sv

The {\tt xx(free)}  function releases the memory block
allocated to a no more useful value. The instruction:
\sv
\indent{\tt xx(free)(\&x);}
\sv\noindent
releases the value pointed by {\tt x} if there is one
and resets the {\tt x} pointer.
After this instruction, the {\tt x} variable is still operational
and may receive a new value.
\sv

Conversion of a big integer into a string is done with
{\tt xx(string\_of)} which allocates a string of appropriate length
and copies into it the decimal representation of its argument. This
string must be released with a call to the
{\tt xx(free\_string)} function.
\sv

Last, the {\tt chrono} function prints the
CPU time in seconds since the beginning of the process, the difference
with the preceding time and the message given as an argument
on the standard error stream.

                          %+---------------+
                          %|  Compilation  |
                          %+---------------+

\section{Compilation}
C programs using \Numerix\ must be compiled with the following command:
\sv
\begin{shelllisting}
\begin{verbatim}
gcc§it options§tt -Dbits_xx -Duse_yyy §it source files§tt -lcnumx
\end{verbatim}
\end{shelllisting}
\sv

{\tt -Dbits\_xx} specifies the bit length of a machine word, ${\tt xx} = 32$ or $64$.
{\tt -Duse\_yyy} specifies which module to use, ${\tt yyy} = {\tt clong}$
or {\tt dlong} or {\tt slong}.
{\tt -lcnumx} adds the
{\tt libcnumx.a} file to the list of libraries in which the linker searches
for external functions.
You may need to add a {\tt -L\it path} option to specify the location
of this {\tt libcnumx.a} file, and a {\tt -I\it path} option 
to inform the preprocessor about the location of
the {\tt c-long\_int.h} header file.


                            %+-----------+
                            %|  Exemple  |
                            %+-----------+

\section{Example}

\begin{clisting}
\begin{verbatim}
                 /* +----------------------------------------+
                    |  File simple.c: Use of Numerix with C  |
                    +----------------------------------------+ */

/* computing (sqrt(3) + sqrt(2))/(sqrt(3)-sqrt(2)) with n digits */

#include <stdlib.h>
#include <stdio.h>
#include "c-long_int.h"

void compute(xint *res, long n) {
   xint ten_n  = xx(new)();
   xint ten_2n = xx(new)();
   xint sqrt_2 = xx(new)();
   xint sqrt_3 = xx(new)();
   xint x      = xx(new)();
   xint y      = xx(new)();

   xx(copy_int)(&ten_n,5);
   xx(pow)  (&ten_n,  ten_n,  n);            /* ten_n <- 5^n ...      */
   xx(shl)  (&ten_n,  ten_n,  n);            /*        ... * 2^n      */
   xx(sqr)  (&ten_2n, ten_n);                /* ten_2n <- 10^(2n)     */
   xx(mul_1)(&sqrt_2, ten_2n, 200);          /* sqrt_2 <- ...         */
   xx(sqrt) (&sqrt_2, sqrt_2);               /* .. sqrt(2*10^(2n+2))  */
   xx(mul_1)(&sqrt_3, ten_2n, 300);          /* sqrt_3 <- ...         */
   xx(sqrt) (&sqrt_3, sqrt_3);               /* .. sqrt(3*10^(2n+2))  */
   xx(add)  (&x,      sqrt_3, sqrt_2);       /* x <- sqrt_3 + sqrt_2  */
   xx(sub)  (&y,      sqrt_3, sqrt_2);       /* y <- sqrt_3 - sqrt_2  */
   xx(mul)  (&x,      ten_n,  x);            /* res <- trunc(10^n*x...*/
   xx(quo)  (res,     x,      y);            /*               ... /y) */
   
   xx(free)(&ten_n);
   xx(free)(&ten_2n);
   xx(free)(&sqrt_2);
   xx(free)(&sqrt_3);
   xx(free)(&x);
   xx(free)(&y);
}


int main(int argc, char **argv) {
  long n = 30;
  xint x = xx(new)();
  char *s;

  for(argc--, argv++; (argc); argc--, argv++) {
    if      (strcmp(*argv,"-test") == 0) {n = 30;}
    else if ((strcmp(*argv,"-n") == 0) && (argc > 0)) {
      argc--, argv++;
      n = atol(*argv);
    } else {
      fprintf(stderr,"syntax: simple [-test] [-n <n>]\n");
      fflush(stderr);
      exit(1);
    }
  }

  compute(&x,n);
  s = xx(string_of)(x);
  fprintf(stdout,"%s\n",s);
  fflush(stdout);

  xx(free)(&x);
  xx(free_string)(s);
  return(0);
}
\end{verbatim}
\end{clisting}
\sv\noindent
Compilation and execution:
\sv
\begin{verbatim}
> gcc -O2 -Wall -Dbits_32 -Duse_slong -o simple simple.c -lcnumx
> ./simple
9898979485566356196394568149410
\end{verbatim}

                     %+-------------------------+
                     %|  Utilisation en Pascal  |
                     %+-------------------------+

\chapter{Use with Pascal}

The Pascal interface of \Numerix\ is built on top of the C interface
and provides the same functionalities. It was developed
on a Linux PC (Athlon processor) with the Free Pascal version 1.0.2 compiler.
\sv

                           %+-------------+
                           %|  Interface  |
                           %+-------------+

\section{Interface}
Three units are defined : {\tt clong}, {\tt dlong} and {\tt slong}.
Each unit contains the declaration of the corresponding big integer type and
the declarations of the associated procedures and functions. The exported identifiers
are the same in each unit, which permits to write user programs
in a unit independent fashion, only the
{\tt uses} clause needs to be changed in order to change the big integer
implementation.
\sv

\begin{camllisting}
\begin{verbatim}
unit clong; (* or dlong or slong *)
interface

(* extensible integer  *)
type xint = ...;

(* allocation/deallocation *)
function  xnew : xint;
procedure xfree(var x : xint);

(* initialization from a long, a big integer or a string *)
function  of_int     (a : longint) : xint;
function  of_xint    (a : xint   ) : xint;
function  of_string  (s : pchar  ) : xint;

(* modification of an integer already initialized *)
procedure copy       (var x : xint; a : xint);                 (* x §la a         *)
procedure copy_int   (var x : xint; a : longint);              (* x §la a         *)
procedure copy_string(var x : xint; s : pchar);                (* x §la val(s)    *)

(* usual operations *)
procedure add     (var x   : xint; a,b   : xint);              (* x §la a+b       *)
procedure sub     (var x   : xint; a,b   : xint);              (* x §la a-b       *)
procedure mul     (var x   : xint; a,b   : xint);              (* x §la ab        *)
procedure quo     (var x   : xint; a,b   : xint);              (* x §la a div b   *)
procedure quomod  (var x,y : xint; a,b   : xint);              (* x §la a div b,  *)
                                                               (* y §la a mod b   *)
procedure gcd     (var z   : xint; a,b   : xint);              (* x §la gcd(a,b)  *)
procedure powmod  (var x   : xint; a,b,c : xint);              (* x §la a^b mod c *)

(* extended gcd : z §la pgcd(a,b), xa-by = z, xr-ys = 1 *)
procedure gcd_ex  (var x,y,z     : xint; a,b : xint);
procedure cfrac   (var r,s,x,y,z : xint; a,b : xint);

(* unary operations *)
procedure abs     (var x   : xint; a     : xint);              (* x §la |a|       *)
procedure neg     (var x   : xint; a     : xint);              (* x §la -a        *)
procedure sqr     (var x   : xint; a     : xint);              (* x §la a^2       *)
procedure sqrt    (var x   : xint; a     : xint);              (* x §la trunc(a^1/2) *)

(* mixed operations *)                            
procedure add_1   (var x   : xint; a     : xint; b : longint); (* x §la a+b       *)
procedure sub_1   (var x   : xint; a     : xint; b : longint); (* x §la a-b       *)
procedure mul_1   (var x   : xint; a     : xint; b : longint); (* x §la ab        *)
function  quomod_1(var x   : xint; a     : xint; b : longint) : longint;
                                                               (* x §la a div b,  *)
                                                               (* returns a mod b *)
procedure shiftl  (var x   : xint; a     : xint; b : longint); (* x §la a*2^b     *)
procedure shiftr  (var x   : xint; a     : xint; b : longint); (* x §la a div 2^b *)
procedure split   (var x,y : xint; a     : xint; b : longint); (* x §la a mod 2^b,*)
                                                               (* y §la a div 2^b *)
procedure join    (var x   : xint; a,b   : xint; c : longint); (* x §la a + b*2^c *)
procedure pow     (var x   : xint; a     : xint; b : longint); (* x §la a^b       *)
procedure root    (var x   : xint; a     : xint; b : longint); (* x §la trunc(a^1/b) *)
procedure fact    (var x   : xint; a     : xint);              (* x §la a!        *)

(* comparison *)
function eq   (a,b : xint) : boolean;                          (* a §eq b ?        *)
function neq  (a,b : xint) : boolean;                          (* a §neq b ?        *)
function inf  (a,b : xint) : boolean;                          (* a §lt b ?        *)
function infeq(a,b : xint) : boolean;                          (* a §le b ?        *)
function sup  (a,b : xint) : boolean;                          (* a §gt b ?        *)
function supeq(a,b : xint) : boolean;                          (* a §ge b ?        *)
function cmp  (a,b : xint) : longint;                          (* sign(a-b)       *)
function sgn  (a   : xint) : longint;                          (* sign(a)         *)

function eq_1   (a : xint; b : longint) : boolean;             (* a §eq b ?        *)
function neq_1  (a : xint; b : longint) : boolean;             (* a §neq b ?        *)
function inf_1  (a : xint; b : longint) : boolean;             (* a §lt b ?        *)
function infeq_1(a : xint; b : longint) : boolean;             (* a §le b ?        *)
function sup_1  (a : xint; b : longint) : boolean;             (* a §gt b ?        *)
function supeq_1(a : xint; b : longint) : boolean;             (* a §ge b ?        *)
function cmp_1  (a : xint; b : longint) : longint;             (* sign(a-b)       *)

(* access to the binary representation, lowbits, highbits and int_of return
  31 bits only for compatibility with Ocaml *)
function nbits   (a : xint)              : longint;            (* size of a       *)
function lowbits (a : xint)              : longint;            (* see Ocaml       *)
function highbits(a : xint)              : longint;            (* see Ocaml       *)
function nth_word(a : xint; n : longint) : longint;            (* bits 16b..16b+15*)
function int_of  (a : xint)              : longint;            (* bits 0..30      *)

(* conversion integer -> string *)
function string_of(x : xint) : ansistring;

(* timing *)
procedure chrono(msg : pchar);

(* errors *)
procedure failwith(msg : pchar);
\end{verbatim}
\end{camllisting}

                          %+--------------+
                          %|  Précisions  |
                          %+--------------+

\section{Details}

A variable of {\tt xint} type is a pointer to a data structure
handled  by the \Numerix\ built-in memory manager.
The initialization of an {\tt x} variable of {\tt xint} type
is usually done in two steps:
\begin{enumerate}
\item initialization of the pointer {\tt x} with a call to {\tt xnew};
\item assignment of a value as the result of some computation, for instance {\tt add(x,a,b)}.
\end{enumerate}

The
{\tt of\_int}, {\tt of\_xint} and {\tt of\_string} functions do
the initialization of the pointer and the assignment of a value
from an ordinary integer, another big integer or a string  in a single
step.
The instruction:
\sv
\indent{\tt x := of\_int($i$);}
\sv\noindent
is formally equivalent to the two instructions:
\sv
\indent{\tt x := xnew; copy\_int(x,$i$);}
\sv\noindent
and similarly for {\tt of\_xint} et {\tt of\_string}.
The execution of an operation with a call such as:
\sv
\indent{\tt quo(x,a,b);}
\sv\noindent
is valid if and only if the following requirements are fulfilled:
\begin{enumerate}
\item the {\tt a} and {\tt b} variables are initialized and point to
valid values for that operation ({\tt a} points to any value
and {\tt b} points to a non zero value);
\item the {\tt x} variable contains an initialized pointer.
\end{enumerate}
\sv

It is not necessary for {\tt x} to point to some value before
this operation. If it does, then the memory block storing this value
will be overwritten with the result if the block is large enough,
otherwise a new memory block will be allocated to store the result, the
{\tt x} pointer will be directed towards this new block and the former one will
be deallocated.
\sv

Read-modify-write operations for which a same variable
is given as operand and result are handled correctly.
On the contrary, for operations returning several results
({\tt quomod}, {\tt gcd\_ex}, {\tt cfrac} and {\tt split}) a single variable
cannot be used for receiving more than one result.
For instance the following instruction is {\it not} allowed:
\sv
\indent{\tt quomod(x,x,a,b); (* \sltt illegal \tt *)}
\sv

The {\tt xfree} procedure releases the memory block
allocated to a no more useful value. The instruction:
\sv
\indent{\tt xfree(x);}
\sv\noindent
releases the value pointed by {\tt x} if there is one
and resets the {\tt x} pointer.
After this instruction, the {\tt x} variable is still operational
and may receive a new value.
\sv

Conversion of a big integer into a string is done with
{\tt string\_of} which allocates a string of appropriate length
and copies into it the decimal representation of its argument. This
string will be automatically released by the Pascal memory manager
as soon as it will not be referenced anymore.
\sv

The {\tt chrono} procedure prints the
CPU time in seconds since the beginning of the process, the difference
with the preceding time and the message given as an argument
on the standard error stream.
\sv

Last, the {\tt failwith} procedure prints its argument on
the standard error stream and stops the program.


                          %+---------------+
                          %|  Compilation  |
                          %+---------------+

\section{Compilation}
Pascal programs using \Numerix\ must be compiled with the following command:
\sv
{\tt ppc386 \it options \tt -Fu\it ppu\_path \tt -Fl\it lib\_path source files}
\sv
{\tt -Fu\it ppu\_path} specifies the directory
containing the compiled {\tt clong.ppu},\break {\tt clong.o},
{\tt dlong.ppu}, {\tt dlong.o}, {\tt slong.ppu} and {\tt slong.o} files.
{\tt -Fl\it lib\_path} specifies the directory containing
the {\tt libcnumx.a} library. Those directives may be omitted
if the files are stored in directories that are automatically searched
by the Pascal compiler.


                            %+-----------+
                            %|  Exemple  |
                            %+-----------+

\section{Example}

\begin{camllisting}
\begin{verbatim}
program simple;

 (* +---------------------------------------------+
    |  File simple.p: Use of Numerix with Pascal  |
    +---------------------------------------------+ *)

(* computing (sqrt(3) + sqrt(2))/(sqrt(3)-sqrt(2)) with n digits *)

uses clong; (* or dlong or slong *)

procedure calcul(var res : xint; n : longint);
var ten_n, ten_2n, sqrt_2, sqrt_3, x, y : xint;
begin
   ten_n  := xnew;
   ten_2n := xnew;
   sqrt_2 := xnew;
   sqrt_3 := xnew;
   x      := xnew;
   y      := xnew;

   copy_int(ten_n,5);
   pow     (ten_n,  ten_n,  n);       (* ten_n <- 5^n ...      *)
   shiftl  (ten_n,  ten_n,  n);       (*        ... * 2^n      *)
   sqr     (ten_2n, ten_n);           (* ten_2n <- 10^(2n)     *)
   mul_1   (sqrt_2, ten_2n, 200);     (* sqrt_2 <- ...         *)
   sqrt    (sqrt_2, sqrt_2);          (* .. sqrt(2*10^(2n+2))  *)
   mul_1   (sqrt_3, ten_2n, 300);     (* sqrt_3 <- ...         *)
   sqrt    (sqrt_3, sqrt_3);          (* .. sqrt(3*10^(2n+2))  *)
   add     (x,      sqrt_3, sqrt_2);  (* x <- sqrt_3 + sqrt_2  *)
   sub     (y,      sqrt_3, sqrt_2);  (* y <- sqrt_3 - sqrt_2  *)
   mul     (x,      ten_n,  x);       (* res <- trunc(10^n*x...*)
   quo     (res,    x,      y);       (*               ... /y) *)
   
   xfree(ten_n);
   xfree(ten_2n);
   xfree(sqrt_2);
   xfree(sqrt_3);
   xfree(x);
   xfree(y);

end;


(* main program *)
var n,i : longint;
    c   : word;
    x   : xint;
begin

   n := 30;
   x := xnew;
   i := 1;
   while i <= paramcount do begin
      if  paramstr(i) = '-test' then n := 30
      else if (paramstr(i) = '-n') and (i < paramcount) then begin
         i := i+1;
         val(paramstr(i),n,c);
      end
      else failwith('syntax: simple [-test] [-n <n>]');
      i := i+1;
   end;

   calcul(x,n);
   writeln(string_of(x));

   xfree(x);
   
end.
\end{verbatim}
\end{camllisting}
\sv\noindent
Compilation and execution:
\sv
\begin{verbatim}
> ppc386 -Fu/home/quercia/lib -Fl/home/quercia/lib simple.p
Free Pascal Compiler version 1.0.2 [2001/03/12] for i386
Copyright (c) 1993-2000 by Florian Klaempfl
Target OS: Linux for i386
Compiling simple.p
Assembling simple
Linking simple
69 Lines compiled, 0.1 sec
> ./simple
9898979485566356196394568149410
\end{verbatim}
                         %+----------------+
                         %|  Installation  |
                         %+----------------+

\chapter{Installation}

                        %+------------------+
                        %|  Téléchargement  |
                        %+------------------+

\section{Downloading}

\Numerix\ is available at the following URL:
\sv
\verb?http://pauillac.inria.fr/~quercia/cdrom/bibs/numerix.tar.gz?
\sv\noindent
You will need the {\tt gcc} C compiler
to compile the C and assembly parts of the library, any
recent version of {\tt gcc} should fit for that. The library was
successfully compiled on a Linux PC with {\tt egcs-2.91.66}
as well as on a Dec workstation
with {\tt gcc 2.7.2.3} for the \Clong\ module only.
\sv
For Ocaml you need a not less than~{\tt 1.05} version
and for Camllight a not less than~{\tt 0.73} version.
Ocaml and Camllight are available at the URL:
\sv
\verb?http://pauillac.inria.fr/caml/index-eng.html?
\sv\noindent
If you want to include the {\tt Gmp} module
in the interfaces for Ocaml and Camllight then you
need \GMP\ installed on your computer.
\GMP\ is available at the URL:
\sv
\verb?http://www.swox.com/gmp/?
\sv
The Pascal interface can be compiled only on a Linux PC
with the Free Pascal compiler which is available at the URL:
\sv
\verb?http://www.freepascal.org/?
\sv
Please note that the Pascal interface requires the {\tt libcnumx.a} library,
therefore this interface can be compiled only if the C interface is also compiled.
\sv
                         %+-----------------+
                         %|  Configuration  |
                         %+-----------------+

\section{Automatic configuration}
Extract the {\tt numerix.tar.gz} archive in a temporary directory
and run the configuration script at the root.
\sv
\noindent
On a Linux PC with the {\tt bash} shell launch:
\sv
\indent\verb?./configure   2>&1 | tee conflog?\par
\sv
\noindent
On a Dec workstation with the {\tt csh} shell launch:
\sv
\indent\verb?./configure       |& tee conflog?\par
\sv
This  script checks which  parts of  \Numerix\ can  be compiled  on your
computer and  creates a {\tt Makefile} file and a {\tt numconf} file
suited  for your configuration.
The {\tt configure} script accepts the following options:

\begin{description}
\item{\tt- -prefix=\it dir}

Set the common root for installation directories:

\indent\verb?INSTALL_LIB     = ?{\it dir}\verb?/lib?,\par
\indent\verb?INSTALL_BIN     = ?{\it dir}\verb?/bin?,\par
\indent\verb?INSTALL_INCLUDE = ?{\it dir}\verb?/include?.\par
The default prefix is \verb?$HOME?.%$

\item{\tt-{}-libdir=\it dir, \tt-{}-bindir=\it dir, \tt-{}-includedir=\it dir}

Set  one  of \verb?INSTALL_LIB?, \verb?INSTALL_BIN?
and \verb?INSTALL_INCLUDE? directory regardless of the others.

\item{\tt-{}-enable-c\rm, \tt-{}-disable-c}

Select or un-select the C interface. The default is to select it.

\item{\tt-{}-enable-caml\rm, \tt-{}-disable-caml}

Select or un-select  the Camllight interface. The default  is to select
it when Camllight is found on  the computer.

\item{\tt-{}-enable-ocaml\rm, \tt-{}-disable-ocaml}

Select or un-select the Ocaml interface. The default is to select it when
Ocaml is  found on the computer.

\item{\tt-{}-enable-pascal\rm, \tt-{}-disable-pascal}

Select or un-select  the Pascal interface. The default  is to select
it when {\tt ppc386} is found on  the computer.

\item{\tt-{}-enable-clong\rm, \tt-{}-disable-clong}

Select or un-select the \Clong\ module. The default is to select it.

\item{\tt-{}-enable-dlong\rm, \tt-{}-disable-dlong}

Select or  un-select the \Dlong\ module.  The default is to  select it when
the C  compiler supports the  double precision integer  datatype ({\tt long
long}) and when this datatype length is twice the length  of a {\tt long}.

\item{\tt-{}-enable-slong\rm, \tt-{}-disable-slong}

Select or  un-select the \Slong\ module.  The default is to  select it when
the processor  is an  Intel x86  one and when  the C  compiler correctly
supports  the double precision  integer datatype.


\item{\tt-{}-enable-gmp\rm, \tt-{}-disable-gmp}

Select or un-select the {\tt Gmp} module.  The default is to select it when the
\GMP\ library is found on the computer.

\item{\tt-{}-enable-caml\_bignum\rm, \tt-{}-disable-caml\_bignum}\par\vskip-5pt\vskip0pt
\item{\tt-{}-enable-ocaml\_bignum\rm, \tt-{}-disable-ocaml\_bignum}

Select or un-select the {\tt Big}  module independently for Camllight and for
Ocaml.  The default  is  to  select it when  the corresponding  {\tt libnums}
library is found on the computer.

\item{\tt-{}-disable-lang}

Un-select   all  the   languages  not   explicitely  selected   with  a
{\tt-{}-enable-xxx} option.

\item{\tt-{}-disable-modules}

Un-select all the modules  not explicitely selected with a {\tt-{}-enable-xxx}
option.

\item{\tt-{}-disable-all}

Un-select all the module/language combinations not explicitely selected
with a {\tt-{}-enable-xxx} option.

\end{description}



                  %+-------------------------------+
                  %|  Edition du fichier numconf   |
                  %+-------------------------------+

\section{Editing the {\tt numconf} file}

Normally the {\tt configure} script should make a suitable {\tt numconf} file.
In case of trouble you can edit this file and change the values chosen
by {\tt configure}. After modifying the {\tt numconf} file you need
to recreate a {\tt Makefile} file in order to take into account the changes
and rewrite the build rules. To update your {\tt Makefile} file just do:
\sv
\indent\verb?make -f numconf makerules?\par
\sv
In the {\tt numconf} file, most of the parameters
should receive a boolean value with the convention
$0 =$ false and $1 =$ true. In case of trouble, have a look at the {\tt logs/pentium/numconf} and
{\tt logs/alpha/numconf} files which contain the settings that were used for tests
on Pentium and Digital alpha processors.

\begin{verbatim}
BITS = 32
\end{verbatim}
Specify the size of a machine word, this should be $32$ or $64$.
\sv

\begin{verbatim}
USE_CLONG        = 1
USE_DLONG        = 1 
USE_SLONG        = 1 
USE_GMP          = 1 
USE_CAML_BIGNUM  = 1
USE_OCAML_BIGNUM = 1
\end{verbatim}
Specify which modules you want to compile, several modules
may be selected. \Dlong\ and \Slong\ modules compile only
on computers with an x86 Intel processor.
Modules {\tt Gmp} and {\tt Big} compile only if you have
\GMP\ and {\tt BigNum} installed.
\sv

\begin{verbatim}
MAKE_C_LIB      = 1
MAKE_OCAML_LIB  = 1
MAKE_CAML_LIB   = 1
MAKE_PASCAL_LIB = 1
\end{verbatim}
Specify which interfaces you want to compile.
\sv

\begin{verbatim}
GCC = gcc -O2 -Wall
AR  = ar -rc
RANLIB = ranlib
\end{verbatim}
Specify the commands to launch to call the C compiler and the librarian.
You can add {\tt -Ixxx} and {\tt -Lxxx} directives if the compiler or
the linker fail to find some header files or libraries.

\begin{verbatim}
OCAML_VERSION = 204
OCAML_LIBDIR  = /usr/local/lib/ocaml
CAML_VERSION  = 074
CAML_LIBDIR   = /usr/local/lib/caml-light
\end{verbatim}
Specify without any period which versions of Ocaml and Camllight
you have and in which directories they are installed.
Those variables are taken into account only if interfaces
for Ocaml and Camllight have to be compiled.
\sv

\begin{verbatim}
CAML       = camlc
CAMLLIBR   = camllibr
CAMLMKTOP  = camlmktop

OCAML      = ocamlc
OCAMLOPT   = ocamlopt
OCAMLMKTOP = ocamlmktop
\end{verbatim}
Specify which commands {\tt make} must launch to call the Camllight compiler,
the Camllight librarian, the Camllight toplevel compiler, the Ocaml
compiler, the Ocaml optimizing compiler, and the Ocaml toplevel
compiler. The values above should be correct, except possibly for path
prefixes.
\sv

\begin{verbatim}
PPC = ppc386
\end{verbatim}
Specify which command {\tt make} must launch to call the Pascal compiler.
The value above should be correct, except possibly for path
prefix and library paths.
\sv

\begin{verbatim}
INSTALL_LIB     = $(HOME)/lib
INSTALL_INCLUDE = $(HOME)/include
INSTALL_BIN     = $(HOME)/bin
\end{verbatim} %$
Specify in which directories the compiled libraries,
the header files (for C interface only) and the binaries
should be installed.
The value of {\tt INSTALL\_LIB} variable will be hard-coded into the customized toplevels
{\tt ocamlnumx} for Ocaml $\geqslant 1.07$ and {\tt camlnumx}
for Camllight $\geqslant 0.74$ so that those toplevels can find
the {\tt numerix.cmi} and {\tt numerix.zi} compiled interfaces by themselves.
Previous versions of Ocaml and Camllight do not provide such a
possibility, and you will have to specify
the path to those compiled interfaces
each time you launch a toplevel  with a {\tt directory} directive.
In the same way, the activation of pretty-printers is done automatically
only with Ocaml-1.07 and Camllight-0.74 or greater;
for previous versions you will have to activate them manually
with the {\tt install\_printer} directive.


            %+------------------------------------------+
            %|  Modification de la bibliothèque Bignum  |
            %+------------------------------------------+

\section{Modifying the Bignum library}
\label{modif-bignum}
Starting with Ocaml-3.00, data external to Ocaml can be compared,
hashed, exported and imported through the generic functions of
Ocaml, provided that the external library implements interfaces
with these generic functions.
The {\tt Clong}, {\tt Dlong}, {\tt Slong} and {\tt Gmp} modules
implement such interfaces, but the {\tt Big\_int} module shipped
with Ocaml implements only
the interfaces with the export and import functions, it lacks
the interfaces with the comparison and hashing functions.
\sv
The {\tt lib/ocaml} directory of \Numerix\ contains a patch file,
{\tt bignum.patch}, implementing these missing interfaces, it can be used
to modify the {\tt Bignum} library so as to make the
generic comparison and hashing functions available within the {\tt Big} module.
\sv
{\it Note: the modifications described below are optional.
If you do not intend to use the {\sltt Big} module, or if you can use it
without generic comparisons and generic hashing, then you are
advised against making these modifications; you can skip to
the next section, {\bf Compilation}, then.
}
\sv
You need Ocaml sources. Unpack them in a temporary directory,
move to the topmost directory of Ocaml distribution
(directory {\tt ocaml-}{\it x.yy}) and launch:
\sv
\noindent\verb?patch -b -p0 <.../numerix-0.19/lib/ocaml/bignum.patch?\par
\sv\noindent
where {\tt ...} denote the directory containing \Numerix\ sources.
The {\tt patch} program must report with a message such as:
\sv
On a Linux PC\sv
\noindent{\sltt patching file otherlibs/num/nat\_stubs.c}\sv
On a Dec workstation\sv
\begin{clisting}\begin{verbatim}§sltt
Hmm...  Looks like a new-style context diff to me...
The text leading up to this was:
--------------------------
|*** otherlibs/num/nat_stubs.c.orig     Fri Aug 24 15:08:51 2001
|--- otherlibs/num/nat_stubs.c  Fri Aug 24 15:46:58 2001
--------------------------
Patching file otherlibs/num/nat_stubs.c using Plan A...
Hunk #1 succeeded at 11.
Hunk #2 succeeded at 30.
Hunk #3 succeeded at 335.
done
\end{verbatim}\end{clisting}
\sv\noindent
If there are no errors, you can rebuild and install the modified Ocaml system.

                          %+---------------+
                          %|  Compilation  |
                          %+---------------+

\section{Compilation}

After editing and adapting the {\tt numconf}  file you can start
the compilation. The targets are:
\begin{description}
\item{\tt lib}:\par
compiles the libraries and the interface files;

\item{\tt examples}:\par
compiles the examples;

\item{\tt test}:\par
executes every example program with the {\tt -test} option;

\item{\tt install}:\par
copies the libraries, the header files and
the binaries in the directories specified by the
{\tt INSTALL\_xxx} variables;

\item{\tt clean}:\par
removes all compiled files.
\end{description}
\sv
\noindent
On a Linux PC with the {\tt bash} shell successively launch:
\sv
\indent\verb?make lib      2>&1 | tee liblog?\par
\indent\verb?make exemples 2>&1 | tee exlog?\par
\indent\verb?make test     2>&1 | tee testlog?\par
\sv

\noindent
On a Dec workstation with the {\tt csh} shell successively launch:
\sv
\indent\verb?make lib      |& tee liblog?\par
\indent\verb?make exemples |& tee exlog?\par
\indent\verb?make test     |& tee testlog?\par
\sv

There should be neither compile error nor warning.
If there are some and if you cannot solve the problem on your own,
please send the
{\tt liblog}, {\tt exlog} and {\tt testlog} log files
to \verb?michel.quercia@prepas.org? for diagnosis.
If you have faced some
problems that you have been able to fix alone, please let me know so
that I may modify the faulty files.
The {\tt logs/alpha/xxxlog} and {\tt logs/pentium/xxxlog} files 
shipped with the distribution contain the compilation logs
for a Linux PC and a Dec workstation, have a look at them in case
of trouble.
\sv

If the compilation and the tests have been successful, you can
install the \Numerix\ library with one of the commands:
\sv
\indent\verb?make install  2>&1 | tee inslog?\par
\indent\verb?make install  |& tee inslog?\par
\sv\noindent
This will copy the files:
\sv
\begin{verbatim}
big.zi       dlong.o      infgmp.zi    numcount.cmi slong.ppu    
camlnumx     dlong.zi     infslong.zi  numerix.a    slong.o      
clong.ppu    gmp.zi       libclnumx.a  numerix.cma  slong.zi     
clong.o      infbig.zi    libcnumx.a   numerix.cmi  
clong.zi     infclong.zi  libmlnumx.a  numerix.cmxa 
dlong.ppu    infdlong.zi  numcmp.cmi   numerix.zo    
\end{verbatim}
in the \verb?$(INSTALL_LIB)? directory, %$
\sv
\begin{verbatim}
c-long_int.h  long_int.h
\end{verbatim}
in the \verb?$(INSTALL_INCLUDE)? directory and %$
\sv
\begin{verbatim}
ocamlnumx
\end{verbatim}
in the \verb?$(INSTALL_BIN)?  directory %$
or only some of them depending on which modules and interfaces you asked
for.
\sv
Now the installation is finished and you can enjoy the
multi-precision programming.
The user guide you are presently reading
is available in the {\tt doc} subdirectory in Postscript
({\tt numerix-eng.ps}) and \LaTeX\ ({\tt numerix-eng.tex}) formats.



                   %+----------------------------+
                   %|  Description des exemples  |
                   %+----------------------------+

\section{Description of the examples}

The subdirectory {\tt exemples} (this is the French spelling for examples)
contain various programs using
\Numerix\ with C, Camllight, Ocaml or Pascal. Each example is in a separate
directory with {\tt c}, {\tt caml}, {\tt ocaml}
and {\tt pascal} subdirectories containing the relevant source files.
\sv

There are two versions for the C-written programs:
one using the \Numerix\ library (file {\tt xxx-long.c}), the other the
\GMP\ library (file {\tt xxx-gmp.c}). Compiled binaries have a name
like:
{\tt xxx-c}, {\tt xxx-d}, {\tt xxx-s} and {\tt xxx-g}, the last letter
showing which module it uses.
\sv

Programs written in Camllight have a single {\tt xxx.mlp} source file
which is compiled into the
{\tt xxx-b}, {\tt xxx-c}, {\tt xxx-d}, {\tt xxx-s} and {\tt xxx-g} binaries,
the last letter showing which module it uses.
\sv

Programs written in Ocaml have a single
{\tt xxx.ml} source file which is compiled into the
{\tt xxx-byte} (compiled with {\tt ocamlc})
and {\tt xxx-opt}  (compiled with {\tt ocamlopt}) binaries.
Each of those binaries contain all the compiled modules
and a particular module is selected at run-time
with the {\tt -e \it module} option, as described in
section~\ref{selmodule}.
\sv
Programs written in Pascal have a single {\tt xxx.p} source file
which is compiled into the
{\tt xxx-c}, {\tt xxx-d} and {\tt xxx-s} binaries,
the last letter showing which unit it uses.


\subsection{chrono}
Speed measurement of the various modules (source in C only).
This program chooses $n$ and $2n$ bits random integers and
measures the running time for various operations between those integers:
\begin{description}
\item\verb?mul   ?: multiplication $n$ bits by $n$ bits;
\item\verb?sqr   ?: square of a number $n$ bit long;
\item\verb?quomod?: division with remainder $2n$ bits by $n$ bits;
\item\verb?quo   ?: division without remainder $2n$ bits by $n$ bits;
\item\verb?sqrt  ?: square root of a $2n$ bit number;
\item\verb?gcd   ?: gcd of two $n$ bit numbers;
\item\verb?gcd_ex?: gcd and Bézout coefficients for two $n$ bit numbers.
\item\verb?all   ?: all operations above.
\end{description}
\sv\noindent
Specify on the command-line the value of $n$ and which operations
to do among {\tt mul}, {\tt sqr}, {\tt quomod}, {\tt quo}, {\tt sqrt}, {\tt gcd} and
{\tt gcd\_ex}.
You can specify a repeat count with a {\tt -r \it r} option.
For instance:
\begin{verbatim}
> exemples/chrono/c/chrono-g -all 1000000
    0.11     0.11 début
    1.15     1.04 mul
    1.84     0.69 sqr
    6.02     4.18 quomod
   10.23     4.21 quo
   40.09    29.86 sqrt
  242.48   202.39 gcd
  698.63   456.15 gcd_ex
> exemples/chrono/c/chrono-s -all 1000000
    0.23     0.23 début
    1.11     0.88 mul
    1.65     0.54 sqr
    6.50     4.85 quomod
   10.62     4.12 quo
   13.93     3.31 sqrt
   45.59    31.66 gcd
   86.28    40.69 gcd_ex
\end{verbatim}
So, on the test computer (Pentium-233Mhz) and with the {\tt Gmp-3} module,
the time for multiplying
two one million bit numbers is $1.04$ seconds, the time for squaring
a one million bit one is $0.69$ seconds, etc. The second run
shows the corresponding timings for the \Slong\ module.

\subsection{hamming}
Computing of the $k^{\hbox{\small th}}$ Hamming number
or the rank of a Hamming number (source in Ocaml only).
The Hamming problem and various algorithms that solve it are described
in the French-written documents:
\sv
\indent\verb?http://pauillac.inria.fr/~quercia/papers/hamming.ps.gz?

\indent\verb?http://pauillac.inria.fr/~quercia/papers/hamming-new.ps.gz?
\sv
The program coming with the \Numerix\ examples implements an
algorithm unpublished with complexity $O(k^{1/3}\ln(k))$
({\tt hamming-new} implements a faster algorithm with complexity $O(\ln(k)^3)$).
The command-line syntax is:
\sv
\indent{\tt hamming-xxx ($k$ \verb?|? $x$ $y$ $z$) [-d] [-v {\it volume}] [-e {\it integers}]}
\sv\noindent
where $k$ is the rank of a Hamming number to be found
and $x,y,z$ are the exponents
of $2,3,5$ in a Hamming number for which the rank is to be searched.
{\tt -d} asks for an output of the different program phases with
timings, {\tt -v \it volume} specifies the method for computing
tetrahedron  volumes (in-place $=$ {\tt surplace}, functional $=$ {\tt func})
and {\tt -e \it integers} specifies which big integer module to use.
For instance:
\sv
\begin{verbatim}
> exemples/hamming/ocaml/hamming-opt -e slong -d -v func 1T
    0.03     0.03 entiers    Slong
    0.03     0.00 volume     func
    0.03     0.00 Paramètres 12081378335  14699735488
    0.03     0.00            19148531618  23298529519
    0.03     0.00            28052091781  34131728817
    0.03     0.00 Approx     338940570505262 -> 1000267456452
    0.03     0.00 Approx     338910358662417 -> 1000000023838
    0.03     0.00 Approx     338910355969313 -> 1000000000001
    0.37     0.34 Exact      338910355969313 -> 1000000000001
    0.40     0.03 n2         338910355969346
    0.42     0.02 n0         338910355969286
    0.50     0.08 n1         338910355969190
    0.51     0.01 Dichotomie 8295 2426 6853
x = 8295  y = 2426  z = 6853
\end{verbatim}
\sv

\subsection{nextpp}
Search for pseudo-prime numbers with the Rabin-Miller test (source in
Ocaml, Caml, C and Pascal).
This program receives two $n$ and $a$ integers (in this order) on the command-line
and searches for the smallest $n+1$ digits integer which is pseudo-prime in
base~$a$. For instance:
\sv
\begin{verbatim}
> time exemples/nextpp/c/nextpp-s 1000 2
453
 
real    0m32.111s
user    0m31.980s
sys     0m0.000s
> time exemples/nextpp/c/nextpp-g 1000 2
453
 
real    0m30.184s
user    0m30.050s
sys     0m0.010s
\end{verbatim}
which means that $10^{1000}+453$ is the smallest integer with~$1001$ digits
pseudo-prime in base~$2$. This is the only program among all examples
for which {\tt Gmp-3} runs faster than \Slong, because of a higher speed
for computing the modular exponentiation.
\sv

\subsection{pi}\label{pi}
Computing the $n$ first decimal digits of $\pi$ (sources in C, Camllight, Ocaml and Pascal).
This program implements the calculation of $\pi$ described
in the {\tt BigNum} reference manual
({\it The Caml Numbers Reference Manual}, Inria, RT-0141)
with a binary summation scheme to speed up the computing of the series
(terms are added two by two, then $4$ by $4$, then $8$ by $8$
and  so on). For instance:
\sv
\begin{verbatim}
> exemples/pi/ocaml/pi-opt -e slong -d 1000000 -skip
    0.03     0.03 Slong, surplace
    1.67     1.64 puiss 5
   19.75    18.08 sqrt
  122.44   102.69 série lb=6875847 ls=6875855
  150.43    27.99 quotient
  186.94    36.51 conversion
3.
14159 26535  89793 23846  26433 83279  50288 41971  69399 37510
... (19998 lignes omises)
56787 96130  33116 46283  99634 64604  22090 10610  57794 58151
\end{verbatim}
\sv

\subsection{simple}
Simple demonstration program (sources in C, Camllight, Ocaml and Pascal).
This program shows how to use the \Numerix\ interfaces.
It computes the $n$ first decimal digits of
$(\sqrt3 + \sqrt2)/(\sqrt3 - \sqrt2)$. For instance:
\sv
\begin{verbatim}
> exemples/simple/ocaml/simple-opt -e slong -n 50  
989897948556635619639456814941178278393189496131335
\end{verbatim}

                    %+---------------------------+
                    %|  Informations techniques  |
                    %+---------------------------+

\chapter{Technical informations}

%--------------------------------------------------------- Algorithmes
\section{Algorithms}

\subsection{Multiplication}
\Numerix\ implements four algorithms for multiplying two big numbers,
each adapted to a specific operand size range.
\sv
\begin{description}
\item{\tt mul\_2}: multiplication of a big integer by a single
or double precision one. This multiplication performs
a simple loop with a complexity $O(n)$ where $n$ denotes
the bit size of the big integer.

\item{\tt mul\_n2}: multiplication of two big integers,
the sorter having at most {\tt klim} digits. This multiplication
performs a double loop with complexity $O(np)$ where $n$
and $p$ denote the operand bit sizes.

\item{\tt karamul}: multiplication of two big integers of digit lengths
between {\tt klim} and {\tt flim} with Karatsuba's ``divide and conquer'' algorithm.
Let $n\leqslant p$ be the operand sizes:
if $n \leqslant p/2$ one splits the $p$-digit operand into two smaller ones
with lengths $n$ and $p-n$ and computes recursively the corresponding products
($n\times n$ and
$n\times(p-n)$). When $n=p$ Karatsuba's multiplication complexity
is $O(n^{\ln(3)/\ln(2)})$.

\item{\tt fftmul}: multiplication of two big integers
of digit lengths $n$, $p$ when $p \geqslant$ {\tt flim} and {\tt klim} $< n \leqslant p$
with Schönage's modular fast Fourier transform algorithm.
The operands and the product are viewed as polynomials
with coefficients belonging to $\mathbb Z/(2^{2^\ell}+1)\mathbb Z$ and
the product of the two input polynomials is computed from its values at
points $2^k$, $0\leqslant k < 2^{\ell+1}$ the set of which is
a cyclic multiplicative subgroup of $(\mathbb Z/(2^{2^\ell}+1)\mathbb Z)^*$.
The parameter $\ell$ chosen depends on the size of the product to be computed
as a {\it number\/}
so as to minimize a rough estimate of the computing time.
Usually $5 \leqslant \ell \leqslant 15$.
The theoretical complexity of Schönage's algorithm is $O(n\ln(n))$
for a $n$ digit product if $\ell$ can fit into a machine word
and $O(n\ln(n)\ln(\ln n))$ otherwise (this case is unconceivable with
today's computers). However the implementation in \Numerix\ follows
a more complicated scheme because of the way of choosing $\ell$.
Experiments show that the computing time is almost linear with respect to~$n$
up to ten million bits, above this limit the performance decreases because of 
memory problems.
\end{description}
\sv
The values of {\tt klim} and {\tt flim} were chosen by trial and error.
For a 32 bits computer with digits of length 32 bits, the values are
 {\tt klim} $= 32$ digits, {\tt flim} $=937$ digits that is to say that one
switches from the naïve $O(n^2)$-multiplication to Karatsuba's one
above $1024$ bits and from Karatsuba's multiplication to
Schönage's one above $30,000$ bits.
\sv

The algorithms for the naïve multiplication and Karatsuba's one are
described in numerous books, for instance
{\it Knuth, The art of computer programming, vol. 2}.
Schönage's modular FFT multiplication is described in an article
written by Paul Zimmermann:
\sv
\verb? http://www.loria.fr/~zimmerma/bignum/schon.ps.gz?
\sv
These algorithms are also used for squaring, taking into account the
simplifications resulting from the equality of the two multiplicands.

\subsection{Division}
\Numerix\ implements three division algorithms
each adapted to a specific ope\-rand size range.
\sv
\begin{description}
\item{\tt quo\_2}: division of a big integer by a single or double
precision one with a simple loop of complexity
$O(n)$ where $n$ denotes the dividend size.

\item{\tt quo\_n2}: division of two big integers with the ``schoolbook''
algorithm when the divisor digit size or the quotient one is smaller
than {\tt klim}. This division has complexity
$O(np)$ where $n$ denotes the divisor size and $p$ denotes the quotient
one.

\item{\tt bzdiv}: division of two big integers with
Burnikel and Ziegler algorithm, which is a ``divide and conquer''
version of the schoolbook algorithm. With this algorithm the time needed
to divide a $2n$ bit number by an $n$ bit one is approximately equal
to twice the time of a $n$ bits by $n$ bits multiplication within
Karatsuba's multiplication range, and approximately equal to $C\ln(n)$
$n$ bits by $n$ bits multiplications within the FFT  multiplication range.
Experiments show that up to ten million bits the time of a
$2n$ bits by $n$ bits division is at most five times greater than
the time of a $n$ bits by $n$ bits multiplication.
\end{description}
\sv

Computing the integer square root of a big integer is done with similar
algorithms: to compute $b=\lfloor\sqrt a\rfloor$
one divides $a$ by $b$, the resulting quotient being $b$, $b+1$ or $b+2$.
In order to perform this division one only needs to know the highest digit
of $b$, the other digits are computed while doing the division. 
This highest digit of $b$ is computed in an independent way with
the Newton method. The time needed to compute
the square root of a $2n$ bit number with this method is
theoretically equal to half the time needed to perform a 
$2n$ bits by $n$ bits division, that is
one $n$ bits par $n$ bits multiplication within
Karatsuba's multiplication range (confirmed by experiments), and $C\ln(n)/2$
$n$ bits by $n$ bits multiplications within the FFT multiplication range
(time observed for $10^7$ bits: 3 multiplications).
\sv

The conversion of a big integer into a decimal string
can be done with successive divisions by~$10$, but this leads to
an algorithm with complexity $O(n^2)$ for an $n$ bit operand.
Therefore \Numerix\ uses another algorithm which consists
in computing by successive squarings a power of~$10$: $10^{2^k}$
the bit length of which lies between
$n/2$ and $n$, then in dividing the input number by $10^{2^k}$
and in converting recursively the quotient and the remainder with the
powers of $10$ already computed. Doing this way,
the time of conversion is approximately twice the time of an $2n$ bits
by $n$ bits division within Karatsuba's multiplication range
and $O(\ln(n))$
$n$ bits by $n$ bits multiplications within the FFT multiplication range.
\sv

\noindent
{\bf Réferences}
\begin{description}
\item{Schoolbook division}:
{\it Knuth, The art of computer programming, vol. 2}

\item{Burnikel and Ziegler division}:
{\it Fast recursive division,
Research report MPI-I-98-1-022, Max Planck Institut Für Informatik, octobre 1998}

\item{Recursive square root (Zimmermann)}:
{\it Karatsuba square root,
INRIA research report no 3805, \tt http://www.inria.fr/RRRT/RR3805.html}

\item{Iterative implementations of Burnikel-Ziegler and Zimmermann algorithms}:\par
{\it Division et racine carrée rapides,\par
\verb?http://pauillac.inria.fr/~quercia/papers/divrap.ps.gz?}
\end{description}


\subsection{Gcd}
Much less optimization effort has been made in the computing
of two integers gcd, only one algorithm is implemented in \Numerix~:
a ``divide and conquer'' version of Lehmer's algorithm.
\sv

Lehmer's algorithm, described in Knuth's book, computes the gcd and
the Bézout coefficients of two big integers $a$ and $b$  by
expanding into a continued fraction the number $a/b$, the quotients
are those of Euclide's algorithm applied to $a$ and $b$.
The quotients are computed from the leading digits $\alpha$
and $\beta$ of~$a$ and~$b$ by simultaneously expanding into continued fractions
$\alpha/(\beta+1)$ and $(\alpha+1)/\beta$.
As $\alpha/(\beta+1) \leqslant a/b
\leqslant (\alpha+1)/\beta$ the quotients for $a/b$ are the same
as those of $\alpha/(\beta+1)$ and $(\alpha+1)/\beta$
as long as the quotients of the two surrounding fractions are equal.
When the first difference appears, one applies the corresponding
homographic transform to $a$ and~$b$ and goes on with the new numbers.
This algorithm has the same asymptotic complexity as Euclide's algorithm,
namely $O(n^2)$ for $n$ bit operands, but most of the operations are
performed on single precision numbers and it is approximately
$20$ times faster than Euclide's algorithm for big operands.
\sv

\Numerix\ implements a ``divide and conquer'' version of Lehmer's algorithm
with $\alpha$ and $\beta$ being the upper halves of
$a$ and $b$ instead of their leading digits which results
in a theoretical complexity of $18$
$n$ bits par $n$ bits multiplication within
Karatsuba's multiplication range (confirmed by experiments), and $O(\ln(n))$
$n$ bits by $n$ bits multiplications within the FFT multiplication range
(time observed for $10^6$ bits: $45$ multiplications).
This recursive version of Lehmer's algorithm is not described in any of
the documents that I read, however Schönage gave a similar algorithm,
called {\it half-gcd\/} or {\it descent},
described in:
\sv
{\it Equation Solving in Terms of Computational Complexity,\par
Proceedings of the International Congress of Mathematicians, 1987}

%------------------------------------------------- Différences avec Numerix-0.13
\section{Differences between versions 0.13 and 0.17 of \Numerix}

\Numerix-0.13 was the first public version, released in February 2000.
The following versions  0.14, 0.15 and 0.16 were small fixes
to compile problems pointed to me by some users, and this
version, \Numerix-0.17, is actually the second public version.
\sv
\noindent{\bf Kernel}:
\begin{description}
\item{}Complete rewrite of the C and assembly kernel so as to facilitate
subsequent upgrades.

\item{}Bug fix in the fast division code
(overflow in a subtraction, pointed to me by YAMAGATA yoriyuki).

\item{}Implementation of Schönage's multiplication.
\end{description}
\sv

\noindent{\bf Caml/Ocaml interface}:
\begin{description}
\item{}Update for Ocaml-3.00.

\item{}Add integer $p$-th root (recursive Newton's algorithm).

\item{}Add modular exponentiation.

\item{}The module {\tt Cmp} is no longer a sub-module of \Numerix,
it is now an independent one: {\tt Numcmp}.

\item{}Add module {\tt Numcount}.

\item{}Merge the compiled code of {\tt Numerix}, {\tt Numcmp}
and {\tt Numcount} into the archives {\tt numerix.cma}, {\tt numerix.cmxa}
instead of {\tt numerix.cmo} and {\tt numerix.cmx}.
\end{description}

%------------------------------------------------- Différences avec Numerix-0.17
\section{Differences between versions 0.17 and 0.18 of \Numerix}

\sv
\noindent{\bf Kernel}:
\begin{description}
\item{}Bug fix for the division with a two digit divisor.

\item{}Modular exponentiation is now coded in C, it is still slower
than \GMP\ when the base is a big number though.

\item{}Fix the compile rules for OpenBSD-2.8.

\end{description}
\sv
\noindent{\bf C interface}:
\begin{description}
\item{}Add the {\tt root} function.
\end{description}
\sv

\noindent{\bf Pascal interface}:
\begin{description}
\item{}First public release of the Pascal interface.
\end{description}

%------------------------------------------------- Différences avec Numerix-0.18
\section{Differences between versions 0.18 and 0.19 of \Numerix}

\sv
\noindent{\bf Ocaml interface}:
\begin{description}
\item{}Remove the comparison operators between big integers from
the {\tt Infixes} module, now Ocaml usual polymorphic comparison operators
can be used.

\item{}Add hash, serialization and deserialization functions.
\end{description}


\vfil\centerline{\vrule height0.4pt width 3cm}
\end{document}

