module Hgmp (isPrime, prevPrime, invert) where
import Numeric.GMP.Utils (withInInteger, withOutInteger_)
import Numeric.GMP.Raw.Safe
import System.IO.Unsafe (unsafePerformIO)
isPrime :: Integer -> Bool
isPrime :: Integer -> Bool
isPrime Integer
x = IO CInt -> CInt
forall a. IO a -> a
unsafePerformIO (Integer -> (Ptr MPZ -> IO CInt) -> IO CInt
forall r. Integer -> (Ptr MPZ -> IO r) -> IO r
withInInteger Integer
x ((Ptr MPZ -> CInt -> IO CInt) -> CInt -> Ptr MPZ -> IO CInt
forall a b c. (a -> b -> c) -> b -> a -> c
flip Ptr MPZ -> CInt -> IO CInt
mpz_probab_prime_p CInt
25)) CInt -> CInt -> Bool
forall a. Ord a => a -> a -> Bool
> CInt
0
prevPrime :: Integer -> Integer
prevPrime :: Integer -> Integer
prevPrime Integer
x
| Integer
x Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
2 = Integer
0
| Integer
x Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
3 = Integer
2
| Bool
otherwise = Integer -> Integer
_prevPrime (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- (Integer
1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ (Integer
x Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` Integer
2)))
where
_prevPrime :: Integer -> Integer
_prevPrime Integer
x
| Integer -> Bool
isPrime Integer
x = Integer
x
| Bool
otherwise = Integer -> Integer
_prevPrime (Integer
xInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
2)
invert :: Integer -> Integer -> Integer
invert :: Integer -> Integer -> Integer
invert Integer
x Integer
m = IO Integer -> Integer
forall a. IO a -> a
unsafePerformIO (IO Integer -> Integer) -> IO Integer -> Integer
forall a b. (a -> b) -> a -> b
$
(Ptr MPZ -> IO CInt) -> IO Integer
forall a. (Ptr MPZ -> IO a) -> IO Integer
withOutInteger_ ((Ptr MPZ -> IO CInt) -> IO Integer)
-> (Ptr MPZ -> IO CInt) -> IO Integer
forall a b. (a -> b) -> a -> b
$ \Ptr MPZ
rop ->
Integer -> (Ptr MPZ -> IO CInt) -> IO CInt
forall r. Integer -> (Ptr MPZ -> IO r) -> IO r
withInInteger Integer
x ((Ptr MPZ -> IO CInt) -> IO CInt)
-> (Ptr MPZ -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \Ptr MPZ
op1 ->
Integer -> (Ptr MPZ -> IO CInt) -> IO CInt
forall r. Integer -> (Ptr MPZ -> IO r) -> IO r
withInInteger Integer
m ((Ptr MPZ -> IO CInt) -> IO CInt)
-> (Ptr MPZ -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \Ptr MPZ
op2 ->
Ptr MPZ -> Ptr MPZ -> Ptr MPZ -> IO CInt
mpz_invert Ptr MPZ
rop Ptr MPZ
op1 Ptr MPZ
op2