Fermat Primality Test
In this task, for a given natural number
- generate a sequence of pseudorandom natural numbers
such that , - test whether
is prime by checking whether the following equation holds for each generated pseudorandom number
If
Pseudo-random Number Generation
To generate pseudorandom numbers in a given interval, use the Linear Congruential Generator (LCG)
where
The number
Haskell
Your task is to implement the Fermat Primality Test in Haskell. Your file should be called Fermat.hs, and you should export the function primality :: Int -> Int -> State LCG Bool. There are two parts to this task: first, implement the LCG, and then the test itself.
Implementation
The LCG generator is represented as
data LCG = LCG Int Int Int Int deriving Showwhere the four Ints in the LCG 4-tuple are
generate_range :: Int -> Int -> State LCG Intwhich is used to sample random integers State monad. So start your code with
import Control.Monad.StateNote that it is desirable to follow
> runState (generate_range 1 100) (LCG 513 1 1 1024)
(20, LCG 513 514 1 1024)Implement the primality test in the function
primality :: Int -> Int -> State LCG Boolwhere the first input is the potential prime and the second is the number of repetitions of the test (i.e., the number of generated pseudorandom numbers). The function is used as follows:
> evalState (primality 17 1000) (LCG 513 1 1 1024)
True
> evalState (primality 42 1000) (LCG 513 1 1 1024)
False
> evalState (primality 9 0) (LCG 513 1 1 1024)
TrueHint
To prevent overflow of Int, compute
Exam Solution
module Fermat (LCG (..), primality) where
import Control.Monad
import Control.Monad.State
-- Linear congruential generator
-- A*x + C mod M
data LCG = LCG Int Int Int Int deriving (Show)
lcg (LCG a x c m) =
let y = (a * x + c) `mod` m
in (y, LCG a y c m)
generate = state lcg
project low high num = (num `mod` (high - low)) + low
generateRange low high = project low high <$> generate
moduloPower a n m = iterate (\x -> x * a `mod` m) 1 !! n
fermatCheck p r = 1 == moduloPower r (p - 1) p
primality :: Int -> Int -> State LCG Bool
primality x n = do
rs <- replicateM n (generateRange 1 x)
pure (all (fermatCheck x) rs)