{-# Language BlockArguments #-}
{-# Language Trustworthy #-}
module LibBF
(
BigFloat
, bfPosZero, bfNegZero
, bfPosInf, bfNegInf
, bfNaN
, bfFromWord
, bfFromInt
, bfFromDouble
, bfFromInteger
, bfFromString
, bfToDouble
, bfToString
, bfToRep
, BFRep(..)
, BFNum(..)
, bfIsFinite
, bfIsZero
, bfIsNaN
, bfCompare
, bfSign
, bfExponent
, Sign(..)
, bfNeg
, bfAdd, bfSub, bfMul, bfDiv
, bfMulWord, bfMulInt, bfMul2Exp
, bfSqrt
, bfPow
, bfRoundFloat, bfRoundInt
, bfUnsafeThaw
, bfUnsafeFreeze
, module LibBF.Opts
) where
import Data.Word
import Data.Int
import System.IO.Unsafe
import LibBF.Mutable as M
import LibBF.Opts
import Control.DeepSeq
newtype BigFloat = BigFloat BF
instance NFData BigFloat where
rnf x = x `seq` ()
instance Show BigFloat where
show = bfToString 16 (showFreeMin Nothing <> addPrefix)
{-# NOINLINE ctxt #-}
{-# OPTIONS_GHC -fno-cse #-}
ctxt :: BFContext
ctxt = unsafePerformIO newContext
newBigFloat :: (BF -> IO ()) -> BigFloat
newBigFloat f = unsafe $
do bf <- new ctxt
f bf
pure (BigFloat bf)
newBigFloat' :: (BF -> IO a) -> (BigFloat,a)
newBigFloat' f = unsafe $
do bf <- new ctxt
a <- f bf
pure (BigFloat bf, a)
unsafe :: IO a -> a
unsafe = unsafePerformIO
bfPosZero :: BigFloat
bfPosZero = newBigFloat (setZero Pos)
bfNegZero :: BigFloat
bfNegZero = newBigFloat (setZero Neg)
bfPosInf :: BigFloat
bfPosInf = newBigFloat (setInf Pos)
bfNegInf :: BigFloat
bfNegInf = newBigFloat (setInf Neg)
bfNaN :: BigFloat
bfNaN = newBigFloat setNaN
bfFromWord :: Word64 -> BigFloat
bfFromWord = newBigFloat . setWord
bfFromInt :: Int64 -> BigFloat
bfFromInt = newBigFloat . setInt
bfFromDouble :: Double -> BigFloat
bfFromDouble = newBigFloat . setDouble
bfFromInteger :: Integer -> BigFloat
bfFromInteger = newBigFloat . setInteger
instance Eq BigFloat where
BigFloat x == BigFloat y = unsafe (cmpEq x y)
instance Ord BigFloat where
BigFloat x < BigFloat y = unsafe (cmpLT x y)
BigFloat x <= BigFloat y = unsafe (cmpLEQ x y)
bfCompare :: BigFloat -> BigFloat -> Ordering
bfCompare (BigFloat x) (BigFloat y) = unsafe (cmp x y)
bfIsFinite :: BigFloat -> Bool
bfIsFinite (BigFloat x) = unsafe (isFinite x)
bfIsNaN :: BigFloat -> Bool
bfIsNaN (BigFloat x) = unsafe (M.isNaN x)
bfSign :: BigFloat -> Maybe Sign
bfSign (BigFloat x) = unsafe (getSign x)
bfExponent :: BigFloat -> Maybe Int64
bfExponent (BigFloat x) = unsafe (getExp x)
bfIsZero :: BigFloat -> Bool
bfIsZero (BigFloat x) = unsafe (isZero x)
bfNeg :: BigFloat -> BigFloat
bfNeg (BigFloat x) = newBigFloat (\bf -> setBF x bf >> fneg bf)
bfAdd :: BFOpts -> BigFloat -> BigFloat -> (BigFloat,Status)
bfAdd opt (BigFloat x) (BigFloat y) = newBigFloat' (fadd opt x y)
bfSub :: BFOpts -> BigFloat -> BigFloat -> (BigFloat,Status)
bfSub opt (BigFloat x) (BigFloat y) = newBigFloat' (fsub opt x y)
bfMul :: BFOpts -> BigFloat -> BigFloat -> (BigFloat,Status)
bfMul opt (BigFloat x) (BigFloat y) = newBigFloat' (fmul opt x y)
bfMulWord :: BFOpts -> BigFloat -> Word64 -> (BigFloat,Status)
bfMulWord opt (BigFloat x) y = newBigFloat' (fmulWord opt x y)
bfMulInt :: BFOpts -> BigFloat -> Int64 -> (BigFloat,Status)
bfMulInt opt (BigFloat x) y = newBigFloat' (fmulInt opt x y)
bfMul2Exp :: BFOpts -> BigFloat -> Int64 -> (BigFloat,Status)
bfMul2Exp opt (BigFloat x) e = newBigFloat' (\p ->
do setBF x p
fmul2Exp opt e p)
bfDiv :: BFOpts -> BigFloat -> BigFloat -> (BigFloat,Status)
bfDiv opt (BigFloat x) (BigFloat y) = newBigFloat' (fdiv opt x y)
bfSqrt :: BFOpts -> BigFloat -> (BigFloat,Status)
bfSqrt opt (BigFloat x) = newBigFloat' (fsqrt opt x)
bfRoundFloat :: BFOpts -> BigFloat -> (BigFloat,Status)
bfRoundFloat opt (BigFloat x) = newBigFloat' (\bf ->
do setBF x bf
fround opt bf
)
bfRoundInt :: BFOpts -> BigFloat -> (BigFloat,Status)
bfRoundInt opt (BigFloat x) = newBigFloat' (\bf ->
do setBF x bf
frint opt bf
)
bfPow :: BFOpts -> BigFloat -> BigFloat -> (BigFloat, Status)
bfPow opts (BigFloat x) (BigFloat y) = newBigFloat' (fpow opts x y)
bfToDouble :: RoundMode -> BigFloat -> (Double, Status)
bfToDouble r (BigFloat x) = unsafe (toDouble r x)
bfToString :: Int -> ShowFmt -> BigFloat -> String
bfToString radix opts (BigFloat x) =
unsafe (toString radix opts x)
bfFromString :: Int -> BFOpts -> String -> (BigFloat,Status)
bfFromString radix opts str =
newBigFloat' \bf ->
do (status,_,usedAll) <- setString radix opts str bf
if usedAll
then pure status
else do setNaN bf
pure Ok
bfToRep :: BigFloat -> BFRep
bfToRep (BigFloat x) = unsafe (toRep x)
bfUnsafeThaw :: BigFloat -> BF
bfUnsafeThaw (BigFloat x) = x
bfUnsafeFreeze :: BF -> BigFloat
bfUnsafeFreeze = BigFloat