\section{Some Integer Functions}
%$Log: IntLib.lhs,v $
%Revision 1.1  2004/08/05 11:13:39  malcolm
%Add a regression testsuite for the nhc98 compiler.  It isn't very good,
%but it is better than nothing.  I've been using it for about four years
%on nightly builds, so it's about time it entered the repository!  It
%includes a slightly altered version of the nofib suite.
%Instructions are in the README.
%
%Revision 1.2  1996/07/25 21:32:53  partain
%Bulk of final changes for 2.01
%
%Revision 1.1  1996/01/08 20:04:20  partain
%Initial revision
%
%Revision 1.1  92/06/30  15:54:07  dlester
%Initial revision
%

In this module we define some useful functions on Integers.

> module IntLib (readInteger, showInteger, makeNumber, chop,
>                powerMod, cubeRoot, log2) where 
> import List--1.3
> rcsid = "$Header: /grp/haskell/cvs-local/nhc98/tests/nofib/spectral/primetest/IntLib.lhs,v 1.1 2004/08/05 11:13:39 malcolm Exp $"

\subsection{Reading and Writing}

> readInteger :: String -> Integer
> readInteger s = read s

> showInteger :: Integer -> String
> showInteger i = show i

\subsection{Interconverting between bases}

We can make a large number from a list of numbers using @makeNumber@.
This satisfies:
\[@makeNumber@ \, @b@ \, [x_0,\,x_1,\,\ldots,\,x_n]
 = x_0.@b@^n + x_1.@b@^{n-1} + \cdots + x_n.@b@^0\]

> makeNumber :: Integer -> [Integer] -> Integer
> makeNumber b = foldl f 0 where f a x = a * b + x

The (left and right) inverse of @makeNumber@ is @chop@.

> chop :: Integer -> Integer -> [Integer]
> chop b = chop' [] where chop' a n = if n == 0 then a else chop' (r:a) q
>                                     where (q,r) = n `divMod` b

\subsection{Raising a number to a power}

The following function @powerMod@ calculates @a^b `mod` m@. I suspect
that this is the critical function in the benchmarking process, and
given that it can be computed {\em without} a great deal of extra
storage, it should be a candidate for being a built-in within the
Haskell library.

> powerMod :: Integer -> Integer -> Integer -> Integer
> powerMod a 0 m = 1
> powerMod a b m
>  = f a' (b-1) a'
>    where a' = a `mod` m
>          f a 0 c = c
>          f a b c = g a b where
>                    g a b | even b    = g ((a*a) `mod` m) (b `div` 2)
>                          | otherwise = f a (b-1) ((a*c) `mod` m)

[This coding of al-Kash\^{\i}'s algorithm is due to Joe Fasel.]

\subsection{Integer Cube roots}

The value $@y@=@cubeRoot x@$ is the integer cube root of @x@, {\it
i.e.} $@y@ = \lfloor \sqrt[3]{@x@} \, \rfloor$. Given $@x@\geq 0$,
@y@ satisfies the following conditions:
\[\begin{array}{lll}
@y@ &\geq & 0, \\
@y@^3 &\geq & @x@, \mbox{ and}\\
(@y@-1)^3 &<& @x@.
\end{array}\]
My implementation uses Newton's method.

> cubeRoot :: Integer -> Integer
> cubeRoot x = until satisfy improve x
>              where satisfy y = y*y*y >= x && y'*y'*y' < x where y' = y-1
>                    improve y = (2*y*y*y+x) `ddiv` (3*y*y)
>                    ddiv a b  = if (r < b `div` 2) then q else q+1
>                                where (q,r) = divMod a b

\subsection{Logarithm base 2}

The $@log2@ n$ is the @Integer@ $m$ such that $m = \lfloor\log_2
n\rfloor$.

> log2 :: Integer -> Integer
> log2 = genericLength . chop 2

This concludes the integer functions needed for the RSA algorithm.

