Flint2-0.1.0.2: src/Data/Number/Flint/Fmpq/Instances.hs
module Data.Number.Flint.Fmpq.Instances (
Fmpq (..)
) where
import System.IO.Unsafe
import Control.Monad
import qualified Data.Ratio as Ratio
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 Data.Char
import Text.Read
import Data.Number.Flint.Fmpz
import Data.Number.Flint.Fmpz.Instances
import Data.Number.Flint.Fmpq
import Data.Number.Flint.Quotient ((//))
instance Show Fmpq where
show x = snd $ unsafePerformIO $ do
let base = 10 :: CInt
withFmpq x $ \x -> do
cs <- fmpq_get_str nullPtr 10 x
s <- peekCString cs
free cs
return s
instance Read Fmpq where
readPrec = parens $
(prec app_prec $ do
x <- step readPrec
Symbol "/" <- lexP
y <- step readPrec
return (x // y))
+++ (prec up_prec $ do
x <- step readPrec
return (x // 1))
where app_prec = 10
up_prec = 5
instance Eq Fmpq where
(==) x y = snd $ snd $ unsafePerformIO $
withFmpq x $ \x ->
withFmpq y $ \y -> do
result <- fmpq_equal x y
return $ result == 1
instance Ord Fmpq where
compare x y = snd $ snd $ unsafePerformIO $
withFmpq x $ \x ->
withFmpq y $ \y -> do
ord <- fmpq_cmp x y
return $ if ord > 0 then GT else (if ord < 0 then LT else EQ)
instance Num Fmpq where
{-# INLINE (+) #-}
(+) = lift2 fmpq_add
{-# INLINE (-) #-}
(-) = lift2 fmpq_sub
{-# INLINE (*) #-}
(*) = lift2 fmpq_mul
negate = lift1 fmpq_neg
abs = lift1 fmpq_abs
fromInteger x = unsafePerformIO $ do
let n = fromInteger x
d = 1 :: Fmpz
result <- newFmpq
withFmpz n $ \n ->
withFmpz d $ \d ->
withFmpq result $ \result -> do
fmpz_one d
fmpq_set_fmpz_frac result n d
fmpq_canonicalise result
return result
signum = lift1 sgn where
sgn result x = do
s <- fmpq_sgn x
fmpq_set_si result (fromIntegral s) 1
instance Fractional Fmpq where
(/) = lift2 fmpq_div
recip = lift1 fmpq_inv
fromRational x = unsafePerformIO $ do
result <- newFmpq
let n = fromInteger $ Ratio.numerator x
d = fromInteger $ Ratio.denominator x
withFmpz n $ \n ->
withFmpz d $ \d ->
withFmpq result $ \result -> do
fmpq_set_fmpz_frac result n d
fmpq_canonicalise result
return result
instance Real Fmpq where
toRational x = unsafePerformIO $ do
p <- newFmpz
q <- newFmpz
withFmpq x $ \x -> do
withFmpz p $ \p -> do
withFmpz q $ \q -> do
fmpq_get_fmpz_frac p q x
return $ (toInteger p) % (toInteger q)
instance RealFrac Fmpq where
properFraction x = unsafePerformIO $ do
p <- newFmpz
q <- newFmpz
r <- newFmpq
withFmpq x $ \x -> do
withFmpz p $ \p -> do
withFmpz q $ \q -> do
withFmpq r $ \r -> do
withNewFmpz $ \tmp -> do
fmpq_get_fmpz_frac p q x
fmpz_tdiv_qr p tmp p q
fmpq_set_fmpz_frac r tmp q
return (fromIntegral p, r)
lift1 f x = fst $ unsafePerformIO $
withNewFmpq $ \result ->
withFmpq x $ \x ->
f result x
lift2 f x y = fst $ unsafePerformIO $
withNewFmpq $ \result ->
withFmpq x $ \x ->
withFmpq y $ \y ->
f result x y