Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
|
|
@ -0,0 +1,44 @@
|
|||
module Primes where
|
||||
|
||||
import System.Random
|
||||
import System.IO.Unsafe
|
||||
|
||||
-- Miller-Rabin wrapped up as an (almost deterministic) pure function
|
||||
isPrime :: Integer -> Bool
|
||||
isPrime n = unsafePerformIO (isMillerRabinPrime 100 n)
|
||||
|
||||
|
||||
isMillerRabinPrime :: Int -> Integer -> IO Bool
|
||||
isMillerRabinPrime k n
|
||||
| even n = return (n==2)
|
||||
| n < 100 = return (n `elem` primesTo100)
|
||||
| otherwise = do ws <- witnesses k n
|
||||
return $ and [test n (pred n) evens (head odds) a | a <- ws]
|
||||
where
|
||||
(evens,odds) = span even (iterate (`div` 2) (pred n))
|
||||
|
||||
test :: Integral nat => nat -> nat -> [nat] -> nat -> nat -> Bool
|
||||
test n n_1 evens d a = x `elem` [1,n_1] || n_1 `elem` powers
|
||||
where
|
||||
x = powerMod n a d
|
||||
powers = map (powerMod n a) evens
|
||||
|
||||
witnesses :: (Num a, Ord a, Random a) => Int -> a -> IO [a]
|
||||
witnesses k n
|
||||
| n < 9080191 = return [31,73]
|
||||
| n < 4759123141 = return [2,7,61]
|
||||
| n < 3474749660383 = return [2,3,5,7,11,13]
|
||||
| n < 341550071728321 = return [2,3,5,7,11,13,17]
|
||||
| otherwise = do g <- newStdGen
|
||||
return $ take k (randomRs (2,n-1) g)
|
||||
|
||||
primesTo100 :: [Integer]
|
||||
primesTo100 = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
|
||||
|
||||
-- powerMod m x n = x^n `mod` m
|
||||
powerMod :: Integral nat => nat -> nat -> nat -> nat
|
||||
powerMod m x n = f (n - 1) x x `rem` m
|
||||
where
|
||||
f d a y = if d==0 then y else g d a y
|
||||
g i b y | even i = g (i `quot` 2) (b*b `rem` m) y
|
||||
| otherwise = f (i-1) b (b*y `rem` m)
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import Control.Monad (liftM)
|
||||
import Data.Bits (Bits, testBit, shiftR)
|
||||
import System.Random (Random, getStdGen, randomRs)
|
||||
import System.IO.Unsafe (unsafePerformIO)
|
||||
import Prelude hiding (even, odd)
|
||||
|
||||
odd :: (Integral a, Bits a) => a -> Bool
|
||||
odd = (`testBit` 0)
|
||||
|
||||
even :: (Integral a, Bits a) => a -> Bool
|
||||
even = not . odd
|
||||
|
||||
-- modPow - Recursive modular exponentiation by taking successive powers of two
|
||||
modPow :: (Integral a, Bits a) => a -> a -> a -> a
|
||||
modPow _ 0 _ = 1
|
||||
modPow base ex m = let term
|
||||
| testBit ex 0 = base `mod` m
|
||||
| otherwise = 1
|
||||
in (term * modPow (base^2 `mod` m) (ex `shiftR` 1) m) `mod` m
|
||||
|
||||
isPrime :: (Integral a, Bits a, Random a) => a -> a -> Bool
|
||||
isPrime n k
|
||||
| n < 4 = if n > 1 then True else False -- Deal with 0-3.
|
||||
| even n = False
|
||||
| otherwise = let randPool = unsafePerformIO $ randNums (n - 2)
|
||||
in witness k randPool
|
||||
where
|
||||
randNums upper = do
|
||||
g <- getStdGen
|
||||
return (randomRs (2, upper) g)
|
||||
|
||||
(d, r) = let decompose d r
|
||||
| odd d = (d, r)
|
||||
| otherwise = decompose (d `shiftR` 1) (r + 1)
|
||||
in decompose (n - 1) 0
|
||||
|
||||
witness 0 _ = True
|
||||
witness k (a:rands)
|
||||
| x == 1 || x == n - 1 = witness (k - 1) rands
|
||||
| otherwise = check x (r - 1)
|
||||
where
|
||||
x = modPow a d n
|
||||
|
||||
check _ 0 = False
|
||||
check x count
|
||||
| x' == 1 = False
|
||||
| x' == n - 1 = witness (k - 1) rands
|
||||
| otherwise = check x' (count - 1)
|
||||
where x' = modPow x 2 n
|
||||
|
||||
-- main function for testing
|
||||
main :: IO()
|
||||
main = do
|
||||
[n,k] <- liftM (map (\x -> read x :: Integer) . words) getLine
|
||||
print $ isPrime n k
|
||||
Loading…
Add table
Add a link
Reference in a new issue