packages feed

chemical-equation-0.0: src/FLINT/Utility.hs

module FLINT.Utility where

import qualified FLINT.MatrixInteger as FmpzMat
import qualified FLINT.Integer as Fmpz
import qualified FLINT.Type as FLINT

import Text.Printf (printf)

import Control.Exception (bracket_)
import Control.Monad (void)
import Control.Applicative ((<$>))

import Foreign.Marshal.Alloc (allocaBytes)
import Foreign.C.String (peekCString, withCString)
import Foreign.C.Types (CLong)
import Foreign.Ptr (Ptr)


withInteger :: (Ptr FLINT.Integer -> IO a) -> IO a
withInteger act =
   allocaBytes FLINT.integerSize $ \ptr ->
   bracket_ (Fmpz.init ptr) (Fmpz.clear ptr) (act ptr)

withMatrix :: CLong -> CLong -> (Ptr FLINT.Matrix -> IO a) -> IO a
withMatrix m n act =
   allocaBytes FLINT.matrixSize $ \mat ->
   bracket_ (FmpzMat.init mat m n) (FmpzMat.clear mat) (act mat)

decimalFromInteger :: Ptr FLINT.Integer -> IO String
decimalFromInteger ptr = do
   let base = 10
   num_digits <- Fmpz.sizeinbase ptr base
   allocaBytes (fromIntegral num_digits + 2) $ \buffer -> do
      void $ Fmpz.get_str buffer base ptr
      peekCString buffer

naturalPreludeFromFlint :: Ptr FLINT.Integer -> IO Integer
naturalPreludeFromFlint ptr = do
   let base = 16
   num_digits <- Fmpz.sizeinbase ptr base
   allocaBytes (fromIntegral num_digits + 2) $ \buffer -> do
      void $ Fmpz.get_str buffer base ptr
      read . ("0x"++) <$> peekCString buffer

integerPreludeFromFlint :: Ptr FLINT.Integer -> IO Integer
integerPreludeFromFlint ptr =
   withInteger $ \absInt -> do
   Fmpz.abs absInt ptr
   sgn <- Fmpz.sgn ptr
   let base = 16
   num_digits <- Fmpz.sizeinbase ptr base
   allocaBytes (fromIntegral num_digits + 2) $ \buffer -> do
      void $ Fmpz.get_str buffer base absInt
      (toInteger sgn *) . read . ("0x"++) <$> peekCString buffer

-- | return sign and turn integer into absolute value
splitSign :: Ptr FLINT.Integer -> IO Ordering
splitSign ptr = do
   sgn <- Fmpz.sgn ptr
   Fmpz.abs ptr ptr
   return $ compare sgn 0

-- | returns success
integerFromDecimal :: Ptr FLINT.Integer -> String -> IO Bool
integerFromDecimal ptr str =
   withCString str $ \strPtr ->
      (0==) <$> Fmpz.set_str ptr strPtr 10

integerFlintFromPrelude :: Ptr FLINT.Integer -> Integer -> IO ()
integerFlintFromPrelude ptr n =
   withCString (printf "%x" n) $ \strPtr ->
      void $ Fmpz.set_str ptr strPtr 16