Miller–Rabin primality test: Difference between revisions
Content added Content deleted
Line 1,183: | Line 1,183: | ||
-- Miller-Rabin wrapped up as an (almost deterministic) pure function |
-- Miller-Rabin wrapped up as an (almost deterministic) pure function |
||
isPrime :: Integer -> Bool |
isPrime :: Integer -> Bool |
||
isPrime n = unsafePerformIO (isMillerRabinPrime n) |
isPrime n = unsafePerformIO (isMillerRabinPrime 100 n) |
||
⚫ | |||
isMillerRabinPrime |
isMillerRabinPrime :: Int -> Integer -> IO Bool |
||
⚫ | |||
| even n = return (n==2) |
| even n = return (n==2) |
||
| n < 100 = return (n `elem` primesTo100) |
| n < 100 = return (n `elem` primesTo100) |
||
| otherwise = do ws <- witnesses |
| otherwise = do ws <- witnesses k n |
||
return $ and |
return $ and [test n (pred n) evens d a | a <- ws] |
||
where |
|||
⚫ | |||
⚫ | |||
test :: Integral nat => nat -> nat -> nat -> Bool |
test :: Integral nat => nat -> nat -> [nat] -> nat -> nat -> Bool |
||
test n n_1 |
test n n_1 evens d a = x `elem` [1,n_1] || n_1 `elem` powers |
||
where |
where |
||
x = powerMod n a d |
|||
⚫ | |||
powers = map (powerMod n |
powers = map (powerMod n a) evens |
||
witnesses :: (Num a, Ord a, Random a) => Int -> a -> IO [a] |
witnesses :: (Num a, Ord a, Random a) => Int -> a -> IO [a] |
||
Line 1,209: | Line 1,214: | ||
primesTo100 :: [Integer] |
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 m x n = x^n `mod` m |
-- powerMod m x n = x^n `mod` m |
||
Line 1,218: | Line 1,224: | ||
| otherwise = f (i-1) b (b*y `rem` m) |
| otherwise = f (i-1) b (b*y `rem` m) |
||
-------------------------------------- |
|||
Testing in GHCi: |
Testing in GHCi: |
||
Line 1,228: | Line 1,235: | ||
*~> dropWhile (<900) $ filter isPrime [2..1000] |
*~> 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> |
||
=={{header|Icon}} and {{header|Unicon}}== |
|||
The following code works in both languages: |
|||
<lang unicon>procedure main() |
|||
every writes(primeTest(901 to 1000, 10)," ") |
|||
write() |
|||
end |
|||
procedure primeTest(n, k) |
|||
if n = 2 then return n |
|||
if n%2 = 0 then fail |
|||
s := 0 |
|||
⚫ | |||
while (d%2 ~= 0, s+:=1, d/:=2) |
|||
every (1 to k, x := ((1+?(n-2))^d)%n) do { |
|||
if x = (1 | (n-1)) then next |
|||
every (1 to s-1, x := (x^2)%n) do { |
|||
if x = 1 then fail |
|||
if x = n-1 then break next |
|||
} |
|||
fail |
|||
} |
|||
return n |
|||
end</lang> |
|||
{{out|Sample run}} |
|||
<pre>->mrpt |
|||
907 911 919 929 937 941 947 953 967 971 977 983 991 997 |
|||
-></pre> |
|||
=={{header|J}}== |
=={{header|J}}== |