module Data.Number.Flint.Fmpz.Instances (
  Fmpz (..)
, UFD (..)
) where

import Test.QuickCheck
import System.IO.Unsafe
import Control.Monad

import Data.Ratio

import Foreign.Storable
import Foreign.C.Types
import Foreign.C.String
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.Marshal.Alloc
import Foreign.Marshal.Array (advancePtr)

import Data.Number.Flint.Fmpz
import Data.Number.Flint.Fmpz.Factor
import Data.Number.Flint.UFD

instance Show Fmpz where
  show :: Fmpz -> String
show Fmpz
x = forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    let base :: CInt
base = CInt
10 :: CInt
    forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
x -> do
      CString
cString <- CString -> CInt -> Ptr CFmpz -> IO CString
fmpz_get_str forall a. Ptr a
nullPtr CInt
base Ptr CFmpz
x
      String
result <- CString -> IO String
peekCString CString
cString
      forall a. Ptr a -> IO ()
free CString
cString
      forall (m :: * -> *) a. Monad m => a -> m a
return String
result

instance Read Fmpz where
  readsPrec :: Int -> ReadS Fmpz
readsPrec Int
d String
s = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    let n :: Integer
        [(Integer
n, String
r)] = forall a. Read a => Int -> ReadS a
readsPrec Int
d String
s
    Fmpz
result <- IO Fmpz
newFmpz
    (Fmpz
_, CInt
flag) <- forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
result forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
result -> 
      forall a. String -> (CString -> IO a) -> IO a
withCString (forall a. Show a => a -> String
show Integer
n) forall a b. (a -> b) -> a -> b
$ \CString
s -> 
        Ptr CFmpz -> CString -> CInt -> IO CInt
fmpz_set_str Ptr CFmpz
result CString
s CInt
10
    if CInt
flag forall a. Eq a => a -> a -> Bool
== CInt
0 then 
      forall (m :: * -> *) a. Monad m => a -> m a
return [(Fmpz
result, String
r)]
    else
      forall (m :: * -> *) a. Monad m => a -> m a
return []

instance Eq Fmpz where
  == :: Fmpz -> Fmpz -> Bool
(==) Fmpz
x Fmpz
y = forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ 
    forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
x ->
      forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
y forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
y -> do
        CInt
result <- Ptr CFmpz -> Ptr CFmpz -> IO CInt
fmpz_equal Ptr CFmpz
x Ptr CFmpz
y
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ CInt
result forall a. Eq a => a -> a -> Bool
== CInt
1

instance Ord Fmpz where
  compare :: Fmpz -> Fmpz -> Ordering
compare Fmpz
x Fmpz
y = forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$
    forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
x ->
      forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
y forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
y -> do
        CInt
ord <- Ptr CFmpz -> Ptr CFmpz -> IO CInt
fmpz_cmp Ptr CFmpz
x Ptr CFmpz
y
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ if CInt
ord forall a. Ord a => a -> a -> Bool
> CInt
0 then Ordering
GT else (if CInt
ord forall a. Ord a => a -> a -> Bool
< CInt
0 then Ordering
LT else Ordering
EQ)

instance Enum Fmpz where
  toEnum :: Int -> Fmpz
toEnum = forall a. Num a => Integer -> a
fromInteger forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral
  fromEnum :: Fmpz -> Int
fromEnum = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Integral a => a -> Integer
toInteger
  succ :: Fmpz -> Fmpz
succ Fmpz
x = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    Fmpz
y <- IO Fmpz
newFmpz 
    forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
x -> forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
y forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
y -> Ptr CFmpz -> Ptr CFmpz -> CULong -> IO ()
fmpz_add_ui Ptr CFmpz
y Ptr CFmpz
x CULong
1
    forall (m :: * -> *) a. Monad m => a -> m a
return Fmpz
y
    
instance Num Fmpz where
  {-# INLINE (+) #-}
  + :: Fmpz -> Fmpz -> Fmpz
(+) = forall {a}.
(Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO a)
-> Fmpz -> Fmpz -> Fmpz
lift2 Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()
fmpz_add
  {-# INLINE (-) #-}
  (-) = forall {a}.
(Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO a)
-> Fmpz -> Fmpz -> Fmpz
lift2 Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()
fmpz_sub
  {-# INLINE (*) #-}
  * :: Fmpz -> Fmpz -> Fmpz
(*) = forall {a}.
(Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO a)
-> Fmpz -> Fmpz -> Fmpz
lift2 Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()
fmpz_mul
  negate :: Fmpz -> Fmpz
negate = forall {a}. (Ptr CFmpz -> Ptr CFmpz -> IO a) -> Fmpz -> Fmpz
lift1 Ptr CFmpz -> Ptr CFmpz -> IO ()
fmpz_neg
  abs :: Fmpz -> Fmpz
abs    = forall {a}. (Ptr CFmpz -> Ptr CFmpz -> IO a) -> Fmpz -> Fmpz
lift1 Ptr CFmpz -> Ptr CFmpz -> IO ()
fmpz_abs
  fromInteger :: Integer -> Fmpz
fromInteger Integer
x = forall a. Read a => String -> a
read (forall a. Show a => a -> String
show Integer
x) :: Fmpz
  signum :: Fmpz -> Fmpz
signum = forall {a}. (Ptr CFmpz -> Ptr CFmpz -> IO a) -> Fmpz -> Fmpz
lift1 Ptr CFmpz -> Ptr CFmpz -> IO ()
sgn where
    sgn :: Ptr CFmpz -> Ptr CFmpz -> IO ()
sgn Ptr CFmpz
result Ptr CFmpz
x = do
      CInt
s <- Ptr CFmpz -> IO CInt
fmpz_sgn Ptr CFmpz
x
      Ptr CFmpz -> CLong -> IO ()
fmpz_set_si Ptr CFmpz
result (forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
s)

instance Real Fmpz where
  toRational :: Fmpz -> Rational
toRational Fmpz
x = (forall a. Integral a => a -> Integer
toInteger Fmpz
x) forall a. Integral a => a -> a -> Ratio a
% Integer
1

instance Integral Fmpz where
  mod :: Fmpz -> Fmpz -> Fmpz
mod Fmpz
x Fmpz
y = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    Fmpz
result <- IO Fmpz
newFmpz
    forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
result forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
result ->
      forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
x ->
        forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
y forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
y -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()
fmpz_mod Ptr CFmpz
result Ptr CFmpz
x Ptr CFmpz
y
    forall (m :: * -> *) a. Monad m => a -> m a
return Fmpz
result
  quotRem :: Fmpz -> Fmpz -> (Fmpz, Fmpz)
quotRem Fmpz
x Fmpz
y = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
    Fmpz
quot <- IO Fmpz
newFmpz
    Fmpz
rem <- IO Fmpz
newFmpz
    forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
x -> 
      forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
y forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
y -> 
        forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
quot forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
quot -> 
          forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
rem forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
rem -> 
            Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO ()
fmpz_tdiv_qr Ptr CFmpz
quot Ptr CFmpz
rem Ptr CFmpz
x Ptr CFmpz
y
    forall (m :: * -> *) a. Monad m => a -> m a
return (Fmpz
quot, Fmpz
rem)
  toInteger :: Fmpz -> Integer
toInteger Fmpz
x = forall a. Read a => String -> a
read (forall a. Show a => a -> String
show Fmpz
x) :: Integer

instance UFD Fmpz where
  factor :: Fmpz -> [(Fmpz, Int)]
factor Fmpz
x = forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> b
snd forall a b. (a -> b) -> a -> b
$ forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$
    forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
y -> do
      CInt
is_one <- Ptr CFmpz -> IO CInt
fmpz_is_one Ptr CFmpz
y
      FmpzFactor
f <- IO FmpzFactor
newFmpzFactor
      forall {a}.
FmpzFactor -> (Ptr CFmpzFactor -> IO a) -> IO (FmpzFactor, a)
withFmpzFactor FmpzFactor
f forall a b. (a -> b) -> a -> b
$ \Ptr CFmpzFactor
f -> do
        if Bool -> Bool
not (CInt
is_one forall a. Eq a => a -> a -> Bool
== CInt
1) then do
          Ptr CFmpzFactor -> Ptr CFmpz -> IO ()
fmpz_factor Ptr CFmpzFactor
f Ptr CFmpz
y
          CFmpzFactor CInt
s Ptr CFmpz
d Ptr CULong
e CLong
_ CLong
n <- forall a. Storable a => Ptr a -> IO a
peek Ptr CFmpzFactor
f
          [(Fmpz, Int)]
result <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Int
0 .. forall a b. (Integral a, Num b) => a -> b
fromIntegral CLong
nforall a. Num a => a -> a -> a
-Int
1] forall a b. (a -> b) -> a -> b
$ \Int
j -> do
            Fmpz
f <- IO Fmpz
newFmpz
            CULong
m <- forall a. Storable a => Ptr a -> IO a
peek (Ptr CULong
e forall a. Storable a => Ptr a -> Int -> Ptr a
`advancePtr` Int
j)
            forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
f forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
f -> Ptr CFmpz -> Ptr CFmpz -> IO ()
fmpz_set Ptr CFmpz
f (Ptr CFmpz
d forall a. Storable a => Ptr a -> Int -> Ptr a
`advancePtr` Int
j)
            forall (m :: * -> *) a. Monad m => a -> m a
return (Fmpz
f, forall a b. (Integral a, Num b) => a -> b
fromIntegral CULong
m)
          forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ if CInt
s forall a. Ord a => a -> a -> Bool
< CInt
1 then (-Fmpz
1, Int
1) forall a. a -> [a] -> [a]
: [(Fmpz, Int)]
result else [(Fmpz, Int)]
result
        else do
          forall (m :: * -> *) a. Monad m => a -> m a
return [(Fmpz
1, Int
1)]

instance Arbitrary Fmpz where
  arbitrary :: Gen Fmpz
arbitrary = do
    Integer
x <- forall a. Arbitrary a => Gen a
arbitrary
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. Num a => Integer -> a
fromInteger Integer
x
      
lift1 :: (Ptr CFmpz -> Ptr CFmpz -> IO a) -> Fmpz -> Fmpz
lift1 Ptr CFmpz -> Ptr CFmpz -> IO a
f Fmpz
x = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
  Fmpz
z <- IO Fmpz
newFmpz
  forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
x ->
    forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
z forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
z -> Ptr CFmpz -> Ptr CFmpz -> IO a
f Ptr CFmpz
z Ptr CFmpz
x
  forall (m :: * -> *) a. Monad m => a -> m a
return Fmpz
z
  
lift2 :: (Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO a)
-> Fmpz -> Fmpz -> Fmpz
lift2 Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO a
f Fmpz
x Fmpz
y = forall a. IO a -> a
unsafePerformIO forall a b. (a -> b) -> a -> b
$ do
  Fmpz
z <- IO Fmpz
newFmpz
  forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
x forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
x ->
    forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
y forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
y ->
      forall {a}. Fmpz -> (Ptr CFmpz -> IO a) -> IO (Fmpz, a)
withFmpz Fmpz
z forall a b. (a -> b) -> a -> b
$ \Ptr CFmpz
z -> Ptr CFmpz -> Ptr CFmpz -> Ptr CFmpz -> IO a
f Ptr CFmpz
z Ptr CFmpz
x Ptr CFmpz
y
  forall (m :: * -> *) a. Monad m => a -> m a
return Fmpz
z