Initial data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 72d218235f
commit f23f22d71c
199087 changed files with 3378941 additions and 0 deletions

View file

@ -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)

View file

@ -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