Miller–Rabin primality test: Difference between revisions
Content added Content deleted
(No function doing the task) |
|||
Line 1,170: | Line 1,170: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
{{works with|Haskell| |
{{works with|Haskell|7.6.3}} |
||
* Ideas taken from [http://primes.utm.edu/prove/prove2_3.html Primality proving] |
* Ideas taken from [http://primes.utm.edu/prove/prove2_3.html Primality proving] |
||
* Functions witns and isMillerRabinPrime follow closely the code outlined in [http://www.jsoftware.com/jwiki/Essays/Primality%20Tests#Miller-Rabin J/Essays] |
* Functions witns and isMillerRabinPrime follow closely the code outlined in [http://www.jsoftware.com/jwiki/Essays/Primality%20Tests#Miller-Rabin J/Essays] |
||
* A useful powerMod function is taken from [[Multiplicative order#Haskell]] |
* A useful powerMod function is taken from [[Multiplicative order#Haskell]] |
||
* Original Rosetta code has been simplified to be easier to follow |
|||
Another Miller Rabin test can be found in D. Amos's Haskell for Math module [http://www.polyomino.f2s.com/david/haskell/numbertheory.html Primes.hs] |
Another Miller Rabin test can be found in D. Amos's Haskell for Math module [http://www.polyomino.f2s.com/david/haskell/numbertheory.html Primes.hs] |
||
<lang Haskell> |
<lang Haskell>module Primes where |
||
import Data.List |
|||
import Control.Monad |
|||
import Control.Arrow |
|||
import System.Random |
|||
import System.IO.Unsafe |
|||
-- Miller-Rabin wrapped up as an (almost deterministic) pure function |
|||
⚫ | |||
isPrime n = unsafePerformIO (isMillerRabinPrime n) |
|||
⚫ | |||
isMillerRabinPrime n |
|||
| even n = return (n==2) |
|||
| n < 100 = return (n `elem` primesTo100) |
|||
⚫ | |||
return $ and (map (test n (pred n)) ws) |
|||
test :: Integral nat => nat -> nat -> nat -> Bool |
|||
test n n_1 w = n_1 `elem` powers || last powers == 1 |
|||
where |
|||
⚫ | |||
powers = map (powerMod n w) (evens ++ take 1 odds) |
|||
⚫ | |||
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] |
|||
⚫ | |||
⚫ | |||
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] |
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 |
-- powerMod m x n = x^n `mod` m |
||
powerMod |
powerMod :: Integral nat => nat -> nat -> nat -> nat |
||
powerMod m x n |
powerMod m x n = f (n - 1) x x `rem` m |
||
where |
|||
f _ 0 y = y |
|||
f a d y |
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 |
| otherwise = f (i-1) b (b*y `rem` m) |
||
⚫ | |||
witns x y = do |
|||
⚫ | |||
let r = [9080191, 4759123141, 2152302898747, 3474749660383, 341550071728321] |
|||
fs = [[31,73],[2,7,61],[2,3,5,7,11],[2,3,5,7,11,13],[2,3,5,7,11,13,17]] |
|||
if y >= 341550071728321 |
|||
⚫ | |||
else return $ snd.head.dropWhile ((<= y).fst) $ zip r fs |
|||
⚫ | |||
⚫ | |||
| n `elem` primesTo100 = return True |
|||
⚫ | |||
let pn = pred n |
|||
⚫ | |||
try = return . all (\a -> let c = map (powerMod n a) e in |
|||
pn `elem` c || last c == 1) |
|||
witns 100 n >>= try</lang> |
|||
Testing in GHCi: |
Testing in GHCi: |
||
<pre>*~> isMillerRabinPrime 4547337172376300111955330758342147474062293202868155909489 |
<pre>*~> isMillerRabinPrime 4547337172376300111955330758342147474062293202868155909489 |
||
Line 1,215: | Line 1,226: | ||
False |
False |
||
*~> |
*~> dropWhile (<900) $ filter isPrime [2..1000] |
||
[907,911,919,929,937,941,947,953,967,971,977,983,991,997]</pre> |
[907,911,919,929,937,941,947,953,967,971,977,983,991,997]</pre> |
||