29 lines
774 B
Haskell
29 lines
774 B
Haskell
import System.Random (randomRIO)
|
|
import ModularArithmeticUtils (modExp, factorOutTwos)
|
|
|
|
millerRabinWitness :: Integer -> Integer -> Integer -> Integer -> Bool
|
|
millerRabinWitness n a d s =
|
|
let x0 = modExp a d n
|
|
in x0 == 1 || x0 == n - 1 || loop x0 (s - 1)
|
|
where
|
|
loop _ 0 = False
|
|
loop x r =
|
|
let x' = (x * x) `mod` n
|
|
in x' == n - 1 || loop x' (r - 1)
|
|
|
|
millerRabin :: Integer -> Integer -> IO Bool
|
|
millerRabin n k
|
|
| n < 2 = return False
|
|
| n == 2 = return True
|
|
| even n = return False
|
|
| otherwise = do
|
|
let (d, s) = factorOutTwos (n - 1)
|
|
go k d s
|
|
where
|
|
go 0 _ _ = return True
|
|
go i d s = do
|
|
a <- randomRIO (2, n - 2)
|
|
if millerRabinWitness n a d s
|
|
then go (i - 1) d s
|
|
else return False
|