\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.