{-# LINE 1 "src/LibBF/Mutable.hsc" #-}
{-# Language ForeignFunctionInterface, CApiFFI #-}
{-# Language PatternSynonyms #-}
{-# Language MultiWayIf #-}
{-# Language BlockArguments #-}
{-# Language DeriveDataTypeable #-}
-- | Mutable big-float computation.
module LibBF.Mutable
  ( -- * Allocation
    newContext, BFContext
  , new, BF

    -- * Assignment
  , setNaN
  , setZero
  , setInf
  , Sign(..)
  , setWord
  , setInt
  , setDouble
  , setInteger
  , setBF
  , setString

    -- * Queries and Comparisons
  , cmpEq
  , cmpLT
  , cmpLEQ
  , cmpAbs
  , cmp
  , getSign
  , getExp

  , isFinite
  , isInf
  , LibBF.Mutable.isNaN
  , isZero

    -- * Arithmetic
  , fneg
  , fadd
  , faddInt
  , fsub
  , fmul
  , fmulInt
  , fmulWord
  , fmul2Exp
  , ffma
  , fdiv
  , frem
  , fsqrt
  , fpow
  , fround
  , frint


  -- * Convert from a number
  , toDouble
  , toString
  , toRep, BFRep(..), BFNum(..)

  -- * Configuration
  , module LibBF.Opts
  , toChunks

  ) where


import Foreign.Marshal.Alloc(alloca,free)
import Foreign.Ptr(Ptr,FunPtr,minusPtr)
import Foreign.ForeignPtr
import Foreign.C.Types
import Foreign.C.String
import Data.Data (Data)
import Data.Word
import Data.Int
import Data.Bits
import Data.Hashable
import Data.List(unfoldr)
import Control.Monad(foldM,when)

import Foreign.Storable



import LibBF.Opts

-- | State of the current computation context.
newtype BFContext = BFContext (ForeignPtr BFContext)

foreign import ccall "bf_context_init_hs"
  bf_context_init_hs :: Ptr BFContext -> IO ()

foreign import ccall "&bf_context_end"
  bf_context_end :: FunPtr (Ptr BFContext -> IO ())

{-| Allocate a new numeric context. -}
newContext :: IO BFContext
newContext :: IO BFContext
newContext =
  do ForeignPtr BFContext
fptr <- forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes (Int
120)
{-# LINE 100 "src/LibBF/Mutable.hsc" #-}
     withForeignPtr fptr bf_context_init_hs
     forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FunPtr (Ptr BFContext -> IO ())
bf_context_end ForeignPtr BFContext
fptr
     forall (f :: * -> *) a. Applicative f => a -> f a
pure (ForeignPtr BFContext -> BFContext
BFContext ForeignPtr BFContext
fptr)


-- | A mutable high precision floating point number.
newtype BF = BF (ForeignPtr BF)

foreign import ccall "bf_init"
  bf_init :: Ptr BFContext -> Ptr BF -> IO ()

foreign import ccall "&bf_delete_hs"
  bf_delete :: FunPtr (Ptr BF -> IO ())

{-| Allocate a new number.  Starts off as zero. -}
new :: BFContext -> IO BF
new :: BFContext -> IO BF
new (BFContext ForeignPtr BFContext
fctx) =
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BFContext
fctx \Ptr BFContext
ctx ->
  do ForeignPtr BF
fptr <- forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes (Int
40)
{-# LINE 119 "src/LibBF/Mutable.hsc" #-}
     withForeignPtr fptr (bf_init ctx)
     forall a. FinalizerPtr a -> ForeignPtr a -> IO ()
addForeignPtrFinalizer FunPtr (Ptr BF -> IO ())
bf_delete ForeignPtr BF
fptr
     forall (f :: * -> *) a. Applicative f => a -> f a
pure (ForeignPtr BF -> BF
BF ForeignPtr BF
fptr)

--------------------------------------------------------------------------------
-- FFI Helpers

signToC :: Sign -> CInt
signToC :: Sign -> CInt
signToC Sign
s = case Sign
s of
              Sign
Pos -> CInt
0
              Sign
Neg -> CInt
1

asSign :: CInt -> Sign
asSign :: CInt -> Sign
asSign CInt
s = if CInt
s forall a. Eq a => a -> a -> Bool
== CInt
0 then Sign
Pos else Sign
Neg

asBool :: CInt -> Bool
asBool :: CInt -> Bool
asBool = (forall a. Eq a => a -> a -> Bool
/= CInt
0)

asOrd :: CInt -> Ordering
asOrd :: CInt -> Ordering
asOrd CInt
x
  | CInt
x forall a. Ord a => a -> a -> Bool
< CInt
0     = Ordering
LT
  | CInt
x forall a. Ord a => a -> a -> Bool
> CInt
0     = Ordering
GT
  | Bool
otherwise = Ordering
EQ


bf1 :: (Ptr BF -> IO a) -> BF -> IO a
bf1 :: forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 Ptr BF -> IO a
f (BF ForeignPtr BF
fout) = forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fout Ptr BF -> IO a
f

bfQuery :: (Ptr BF -> IO CInt) -> BF -> IO Bool
bfQuery :: (Ptr BF -> IO CInt) -> BF -> IO Bool
bfQuery Ptr BF -> IO CInt
f = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CInt -> Bool
asBool forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr BF -> IO CInt
f)

bfRel :: (Ptr BF -> Ptr BF -> IO CInt) -> BF -> BF -> IO Bool
bfRel :: (Ptr BF -> Ptr BF -> IO CInt) -> BF -> BF -> IO Bool
bfRel Ptr BF -> Ptr BF -> IO CInt
f = forall a. (Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> IO a
bf2 \Ptr BF
x Ptr BF
y -> CInt -> Bool
asBool forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr BF -> Ptr BF -> IO CInt
f Ptr BF
y Ptr BF
x

bfOrd :: (Ptr BF -> Ptr BF -> IO CInt) -> BF -> BF -> IO Ordering
bfOrd :: (Ptr BF -> Ptr BF -> IO CInt) -> BF -> BF -> IO Ordering
bfOrd Ptr BF -> Ptr BF -> IO CInt
f = forall a. (Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> IO a
bf2 \Ptr BF
x Ptr BF
y -> CInt -> Ordering
asOrd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr BF -> Ptr BF -> IO CInt
f Ptr BF
y Ptr BF
x

bf2 :: (Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> IO a
bf2 :: forall a. (Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> IO a
bf2 Ptr BF -> Ptr BF -> IO a
f (BF ForeignPtr BF
fin1) (BF ForeignPtr BF
fout) =
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fin1 \Ptr BF
in1 ->
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fout \Ptr BF
out1 ->
    Ptr BF -> Ptr BF -> IO a
f Ptr BF
out1 Ptr BF
in1

bf3 :: (Ptr BF -> Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> BF -> IO a
bf3 :: forall a.
(Ptr BF -> Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> BF -> IO a
bf3 Ptr BF -> Ptr BF -> Ptr BF -> IO a
f (BF ForeignPtr BF
fin1) (BF ForeignPtr BF
fin2) (BF ForeignPtr BF
fout) =
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fin1 \Ptr BF
in1 ->
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fin2 \Ptr BF
in2 ->
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fout \Ptr BF
out ->
    Ptr BF -> Ptr BF -> Ptr BF -> IO a
f Ptr BF
out Ptr BF
in1 Ptr BF
in2






--------------------------------------------------------------------------------
-- Assignment


-- | Indicates if a number is positive or negative.
data Sign = Neg {-^ Negative -} | Pos {-^ Positive -}
             deriving (Typeable Sign
Sign -> DataType
Sign -> Constr
(forall b. Data b => b -> b) -> Sign -> Sign
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Sign -> u
forall u. (forall d. Data d => d -> u) -> Sign -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Sign -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Sign -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Sign -> m Sign
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Sign -> m Sign
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Sign
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Sign -> c Sign
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Sign)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Sign)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Sign -> m Sign
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Sign -> m Sign
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Sign -> m Sign
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Sign -> m Sign
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Sign -> m Sign
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Sign -> m Sign
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Sign -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Sign -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> Sign -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Sign -> [u]
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Sign -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Sign -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Sign -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Sign -> r
gmapT :: (forall b. Data b => b -> b) -> Sign -> Sign
$cgmapT :: (forall b. Data b => b -> b) -> Sign -> Sign
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Sign)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Sign)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Sign)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Sign)
dataTypeOf :: Sign -> DataType
$cdataTypeOf :: Sign -> DataType
toConstr :: Sign -> Constr
$ctoConstr :: Sign -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Sign
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Sign
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Sign -> c Sign
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Sign -> c Sign
Data,Sign -> Sign -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Sign -> Sign -> Bool
$c/= :: Sign -> Sign -> Bool
== :: Sign -> Sign -> Bool
$c== :: Sign -> Sign -> Bool
Eq,Eq Sign
Sign -> Sign -> Bool
Sign -> Sign -> Ordering
Sign -> Sign -> Sign
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Sign -> Sign -> Sign
$cmin :: Sign -> Sign -> Sign
max :: Sign -> Sign -> Sign
$cmax :: Sign -> Sign -> Sign
>= :: Sign -> Sign -> Bool
$c>= :: Sign -> Sign -> Bool
> :: Sign -> Sign -> Bool
$c> :: Sign -> Sign -> Bool
<= :: Sign -> Sign -> Bool
$c<= :: Sign -> Sign -> Bool
< :: Sign -> Sign -> Bool
$c< :: Sign -> Sign -> Bool
compare :: Sign -> Sign -> Ordering
$ccompare :: Sign -> Sign -> Ordering
Ord,Int -> Sign -> ShowS
[Sign] -> ShowS
Sign -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Sign] -> ShowS
$cshowList :: [Sign] -> ShowS
show :: Sign -> String
$cshow :: Sign -> String
showsPrec :: Int -> Sign -> ShowS
$cshowsPrec :: Int -> Sign -> ShowS
Show)


foreign import ccall "bf_set_nan"
  bf_set_nan :: Ptr BF -> IO ()

-- | Assign @NaN@ to the number.
setNaN :: BF -> IO ()
setNaN :: BF -> IO ()
setNaN (BF ForeignPtr BF
fptr) = forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fptr Ptr BF -> IO ()
bf_set_nan


foreign import ccall "bf_set_zero"
  bf_set_zero :: Ptr BF -> CInt -> IO ()

-- | Assign a zero to the number.
setZero :: Sign -> BF -> IO ()
setZero :: Sign -> BF -> IO ()
setZero Sign
sig = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (Ptr BF -> CInt -> IO ()
`bf_set_zero` Sign -> CInt
signToC Sign
sig)


foreign import ccall "bf_set_inf"
  bf_set_inf :: Ptr BF -> CInt -> IO ()

-- | Assign an infinty to the number.
setInf :: Sign -> BF -> IO ()
setInf :: Sign -> BF -> IO ()
setInf Sign
sig = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (Ptr BF -> CInt -> IO ()
`bf_set_inf` Sign -> CInt
signToC Sign
sig)


foreign import ccall "bf_set_ui"
  bf_set_ui :: Ptr BF -> Word64 -> IO ()

{-| Assign from a word -}
setWord :: Word64 -> BF -> IO ()
setWord :: LimbT -> BF -> IO ()
setWord LimbT
w = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (Ptr BF -> LimbT -> IO ()
`bf_set_ui` LimbT
w)


foreign import ccall "bf_set_si"
  bf_set_si :: Ptr BF -> Int64 -> IO ()

{-| Assign from an int -}
setInt :: Int64 -> BF -> IO ()
setInt :: SLimbT -> BF -> IO ()
setInt SLimbT
s = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (Ptr BF -> SLimbT -> IO ()
`bf_set_si` SLimbT
s)

-- | Set an integer.  If the integer is larger than the primitive types,
-- this does repreated Int64 additions and multiplications.
setInteger :: Integer -> BF -> IO ()
setInteger :: Integer -> BF -> IO ()
setInteger Integer
n0 BF
bf0
  | Integer
n0 forall a. Ord a => a -> a -> Bool
>= Integer
0 Bool -> Bool -> Bool
&& Integer
n0 forall a. Ord a => a -> a -> Bool
<= forall a. Integral a => a -> Integer
toInteger (forall a. Bounded a => a
maxBound :: Word64) =
    LimbT -> BF -> IO ()
setWord (forall a. Num a => Integer -> a
fromInteger Integer
n0) BF
bf0
  | Integer
n0 forall a. Ord a => a -> a -> Bool
< Integer
0 Bool -> Bool -> Bool
&& Integer
n0 forall a. Ord a => a -> a -> Bool
>= forall a. Integral a => a -> Integer
toInteger (forall a. Bounded a => a
minBound :: Int64) =
    SLimbT -> BF -> IO ()
setInt (forall a. Num a => Integer -> a
fromInteger Integer
n0) BF
bf0
  | Bool
otherwise =
  do Sign -> BF -> IO ()
setZero Sign
Pos BF
bf0
     Integer -> BF -> IO ()
go (forall a. Num a => a -> a
abs Integer
n0) BF
bf0
     forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Integer
n0 forall a. Ord a => a -> a -> Bool
< Integer
0) (BF -> IO ()
fneg BF
bf0)
  where
  chunk :: Integer
chunk = forall a. Integral a => a -> Integer
toInteger (forall a. Bounded a => a
maxBound :: Int64) forall a. Num a => a -> a -> a
+ Integer
1

  go :: Integer -> BF -> IO ()
go Integer
n BF
bf
    | Integer
n forall a. Eq a => a -> a -> Bool
== Integer
0 = forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    | Bool
otherwise =
      do let (Integer
next,Integer
this) = Integer
n forall a. Integral a => a -> a -> (a, a)
`divMod` Integer
chunk
         Integer -> BF -> IO ()
go Integer
next BF
bf
         Status
Ok <- BFOpts -> BF -> LimbT -> BF -> IO Status
fmulWord BFOpts
infPrec BF
bf (forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
chunk) BF
bf
         Status
Ok <- BFOpts -> BF -> SLimbT -> BF -> IO Status
faddInt  BFOpts
infPrec BF
bf (forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
this)  BF
bf
         forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

-- | Chunk a non-negative integer into words,
-- least significatn first
toChunks :: Integer -> [LimbT]
toChunks :: Integer -> [LimbT]
toChunks = forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr Integer -> Maybe (LimbT, Integer)
step
  where
  step :: Integer -> Maybe (LimbT, Integer)
step Integer
n = if Integer
n forall a. Eq a => a -> a -> Bool
== Integer
0 then forall a. Maybe a
Nothing
                     else forall a. a -> Maybe a
Just (Integer -> LimbT
leastChunk Integer
n, Integer
n forall a. Bits a => a -> Int -> a
`shiftR` Int
unit)

  unit :: Int
unit = Int
64 :: Int
{-# LINE 255 "src/LibBF/Mutable.hsc" #-}
  mask = (1 `shiftL` unit) - 1

  leastChunk :: Integer -> LimbT
  leastChunk :: Integer -> LimbT
leastChunk Integer
n = forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer
n forall a. Bits a => a -> a -> a
.&. Integer
mask)



foreign import ccall "bf_set_float64"
  bf_set_float64 :: Ptr BF -> Double -> IO ()

{-| Assign from a double -}
setDouble :: Double -> BF -> IO ()
setDouble :: Double -> BF -> IO ()
setDouble Double
d = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (Ptr BF -> Double -> IO ()
`bf_set_float64` Double
d)


foreign import ccall "bf_set"
  bf_set :: Ptr BF -> Ptr BF -> IO ()

{-| Assign from another number. -}
setBF :: BF -> BF {-^ This number is changed -} -> IO ()
setBF :: BF -> BF -> IO ()
setBF = forall a. (Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> IO a
bf2 (\Ptr BF
out Ptr BF
in1 -> Ptr BF -> Ptr BF -> IO ()
bf_set Ptr BF
out Ptr BF
in1)


--------------------------------------------------------------------------------
-- Comparisons

foreign import capi "libbf.h bf_cmp_eq"
  bf_cmp_eq :: Ptr BF -> Ptr BF -> IO CInt

{-| Check if the two numbers are equal. -}
cmpEq :: BF -> BF -> IO Bool
cmpEq :: BF -> BF -> IO Bool
cmpEq = (Ptr BF -> Ptr BF -> IO CInt) -> BF -> BF -> IO Bool
bfRel Ptr BF -> Ptr BF -> IO CInt
bf_cmp_eq


foreign import capi "libbf.h bf_cmp_lt"
  bf_cmp_lt :: Ptr BF -> Ptr BF -> IO CInt

{-| Check if the first number is strictly less than the second. -}
cmpLT :: BF -> BF -> IO Bool
cmpLT :: BF -> BF -> IO Bool
cmpLT = (Ptr BF -> Ptr BF -> IO CInt) -> BF -> BF -> IO Bool
bfRel Ptr BF -> Ptr BF -> IO CInt
bf_cmp_lt


foreign import capi "libbf.h bf_cmp_le"
  bf_cmp_le :: Ptr BF -> Ptr BF -> IO CInt

{-| Check if the first number is less than, or equal to, the second. -}
cmpLEQ :: BF -> BF -> IO Bool
cmpLEQ :: BF -> BF -> IO Bool
cmpLEQ = (Ptr BF -> Ptr BF -> IO CInt) -> BF -> BF -> IO Bool
bfRel Ptr BF -> Ptr BF -> IO CInt
bf_cmp_le


foreign import ccall "bf_cmpu"
  bf_cmpu :: Ptr BF -> Ptr BF -> IO CInt

{-| Compare the absolute values of the two numbers. See also 'cmp'. -}
cmpAbs :: BF -> BF -> IO Ordering
cmpAbs :: BF -> BF -> IO Ordering
cmpAbs = (Ptr BF -> Ptr BF -> IO CInt) -> BF -> BF -> IO Ordering
bfOrd Ptr BF -> Ptr BF -> IO CInt
bf_cmpu


foreign import ccall "bf_cmp_full"
  bf_cmp_full :: Ptr BF -> Ptr BF -> IO CInt

{-| Compare the two numbers.  The special values are ordered like this:

      * -0 < 0
      * NaN == NaN
      * NaN is larger than all other numbers
-}
cmp :: BF -> BF -> IO Ordering
cmp :: BF -> BF -> IO Ordering
cmp = (Ptr BF -> Ptr BF -> IO CInt) -> BF -> BF -> IO Ordering
bfOrd Ptr BF -> Ptr BF -> IO CInt
bf_cmp_full







foreign import capi "libbf.h bf_is_finite"
  bf_is_finite :: Ptr BF -> IO CInt

foreign import capi "libbf.h bf_is_nan"
  bf_is_nan :: Ptr BF -> IO CInt

foreign import capi "libbf.h bf_is_zero"
  bf_is_zero :: Ptr BF -> IO CInt

{-| Check if the number is "normal", i.e. (not infinite or NaN) -}
isFinite :: BF -> IO Bool
isFinite :: BF -> IO Bool
isFinite = (Ptr BF -> IO CInt) -> BF -> IO Bool
bfQuery Ptr BF -> IO CInt
bf_is_finite

{-| Check if the number is NaN -}
isNaN :: BF -> IO Bool
isNaN :: BF -> IO Bool
isNaN = (Ptr BF -> IO CInt) -> BF -> IO Bool
bfQuery Ptr BF -> IO CInt
bf_is_nan

{-| Check if the given number is a zero. -}
isZero :: BF -> IO Bool
isZero :: BF -> IO Bool
isZero = (Ptr BF -> IO CInt) -> BF -> IO Bool
bfQuery Ptr BF -> IO CInt
bf_is_zero

foreign import capi "libbf.h bf_neg"
  bf_neg :: Ptr BF -> IO ()

foreign import ccall "bf_add"
  bf_add :: Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status

foreign import ccall "bf_add_si"
  bf_add_si :: Ptr BF -> Ptr BF -> Int64 -> LimbT -> FlagsT -> IO Status

foreign import ccall "bf_sub"
  bf_sub :: Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status

foreign import ccall "bf_mul"
  bf_mul :: Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status

foreign import ccall "bf_mul_si"
  bf_mul_si :: Ptr BF -> Ptr BF -> Int64 -> LimbT -> FlagsT -> IO Status

foreign import ccall "bf_mul_ui"
  bf_mul_ui :: Ptr BF -> Ptr BF -> Word64 -> LimbT -> FlagsT -> IO Status

foreign import ccall "bf_mul_2exp"
  bf_mul_2exp :: Ptr BF -> SLimbT -> LimbT -> FlagsT -> IO Status

foreign import ccall "bf_div"
  bf_div :: Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status

foreign import ccall "bf_rem"
  bf_rem :: Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> CInt -> IO Status

foreign import ccall "bf_pow"
  bf_pow :: Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status

foreign import ccall "bf_round"
  bf_round :: Ptr BF -> LimbT -> FlagsT -> IO Status

foreign import ccall "bf_rint"
  bf_rint :: Ptr BF -> CInt -> IO Status

foreign import ccall "bf_sqrt"
  bf_sqrt :: Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status



bfArith :: (Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status) ->
           BFOpts -> BF -> BF -> BF -> IO Status
bfArith :: (Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status)
-> BFOpts -> BF -> BF -> BF -> IO Status
bfArith Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status
fun (BFOpts LimbT
prec FlagsT
flags) (BF ForeignPtr BF
fa) (BF ForeignPtr BF
fb) (BF ForeignPtr BF
fr) =
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fa \Ptr BF
a ->
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fb \Ptr BF
b ->
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fr \Ptr BF
r ->
  Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status
fun Ptr BF
r Ptr BF
a Ptr BF
b LimbT
prec FlagsT
flags


-- | Negate the number.
fneg :: BF -> IO ()
fneg :: BF -> IO ()
fneg = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 Ptr BF -> IO ()
bf_neg

-- | Add two numbers, using the given settings, and store the
-- result in the last.
fadd :: BFOpts -> BF -> BF -> BF -> IO Status
fadd :: BFOpts -> BF -> BF -> BF -> IO Status
fadd = (Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status)
-> BFOpts -> BF -> BF -> BF -> IO Status
bfArith Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status
bf_add

-- | Add a number and an int64 and store the result in the last.
faddInt :: BFOpts -> BF -> Int64 -> BF -> IO Status
faddInt :: BFOpts -> BF -> SLimbT -> BF -> IO Status
faddInt (BFOpts LimbT
p FlagsT
f) BF
x SLimbT
y BF
z = forall a. (Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> IO a
bf2 (\Ptr BF
out Ptr BF
in1 -> Ptr BF -> Ptr BF -> SLimbT -> LimbT -> FlagsT -> IO Status
bf_add_si Ptr BF
out Ptr BF
in1 SLimbT
y LimbT
p FlagsT
f) BF
x BF
z

-- | Subtract two numbers, using the given settings, and store the
-- result in the last.
fsub :: BFOpts -> BF -> BF -> BF -> IO Status
fsub :: BFOpts -> BF -> BF -> BF -> IO Status
fsub = (Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status)
-> BFOpts -> BF -> BF -> BF -> IO Status
bfArith Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status
bf_sub

-- | Multiply two numbers, using the given settings, and store the
-- result in the last.
fmul :: BFOpts -> BF -> BF -> BF -> IO Status
fmul :: BFOpts -> BF -> BF -> BF -> IO Status
fmul = (Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status)
-> BFOpts -> BF -> BF -> BF -> IO Status
bfArith Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status
bf_mul

-- | Compute the fused-multiply-add.
--   @ffma opts x y z r@ computes @r := (x*y)+z@.
ffma :: BFOpts -> BF -> BF -> BF -> BF -> IO Status
ffma :: BFOpts -> BF -> BF -> BF -> BF -> IO Status
ffma (BFOpts LimbT
prec FlagsT
f) (BF ForeignPtr BF
x) (BF ForeignPtr BF
y) (BF ForeignPtr BF
z) (BF ForeignPtr BF
r) =
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
x \Ptr BF
xp ->
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
y \Ptr BF
yp ->
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
z \Ptr BF
zp ->
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
r \Ptr BF
out ->
    do Status
s1 <- Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status
bf_mul Ptr BF
out Ptr BF
xp Ptr BF
yp LimbT
4611686018427387903 FlagsT
0
{-# LINE 437 "src/LibBF/Mutable.hsc" #-}
       case s1 of
         MemError -> return s1
         _ ->
           do s2 <- bf_add out out zp prec f
              pure (s1 <> s2)

-- | Multiply the number by the given word, and store the result
-- in the second number.
fmulWord :: BFOpts -> BF -> Word64 -> BF -> IO Status
fmulWord :: BFOpts -> BF -> LimbT -> BF -> IO Status
fmulWord (BFOpts LimbT
p FlagsT
f) BF
x LimbT
y BF
z = forall a. (Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> IO a
bf2 (\Ptr BF
out Ptr BF
in1 -> Ptr BF -> Ptr BF -> LimbT -> LimbT -> FlagsT -> IO Status
bf_mul_ui Ptr BF
out Ptr BF
in1 LimbT
y LimbT
p FlagsT
f) BF
x BF
z

-- | Multiply the number by the given int, and store the result
-- in the second number.
fmulInt :: BFOpts -> BF -> Int64 -> BF -> IO Status
fmulInt :: BFOpts -> BF -> SLimbT -> BF -> IO Status
fmulInt (BFOpts LimbT
p FlagsT
f) BF
x SLimbT
y BF
z = forall a. (Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> IO a
bf2 (\Ptr BF
out Ptr BF
in1 -> Ptr BF -> Ptr BF -> SLimbT -> LimbT -> FlagsT -> IO Status
bf_mul_si Ptr BF
out Ptr BF
in1 SLimbT
y LimbT
p FlagsT
f) BF
x BF
z

-- | Multiply the number by @2^e@.
fmul2Exp :: BFOpts -> Int -> BF -> IO Status
fmul2Exp :: BFOpts -> Int -> BF -> IO Status
fmul2Exp (BFOpts LimbT
p FlagsT
f) Int
e = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (\Ptr BF
out -> Ptr BF -> SLimbT -> LimbT -> FlagsT -> IO Status
bf_mul_2exp Ptr BF
out (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
e :: SLimbT) LimbT
p FlagsT
f)

-- | Divide two numbers, using the given settings, and store the
-- result in the last.
fdiv :: BFOpts -> BF -> BF -> BF -> IO Status
fdiv :: BFOpts -> BF -> BF -> BF -> IO Status
fdiv = (Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status)
-> BFOpts -> BF -> BF -> BF -> IO Status
bfArith Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status
bf_div

-- | Compute the remainder @x - y * n@ where @n@ is the integer
--   nearest to @x/y@ (with ties broken to even values of @n@).
--   Output is written into the final argument.
frem :: BFOpts -> BF -> BF -> BF -> IO Status
frem :: BFOpts -> BF -> BF -> BF -> IO Status
frem (BFOpts LimbT
p FlagsT
f) (BF ForeignPtr BF
fin1) (BF ForeignPtr BF
fin2) (BF ForeignPtr BF
fout) =
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fin1 \Ptr BF
in1 ->
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fin2 \Ptr BF
in2 ->
  forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr BF
fout \Ptr BF
out ->
    Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> CInt -> IO Status
bf_rem Ptr BF
out Ptr BF
in1 Ptr BF
in2 LimbT
p FlagsT
f CInt
0
{-# LINE 471 "src/LibBF/Mutable.hsc" #-}

-- | Compute the square root of the first number and store the result
-- in the second.
fsqrt :: BFOpts -> BF -> BF -> IO Status
fsqrt :: BFOpts -> BF -> BF -> IO Status
fsqrt (BFOpts LimbT
p FlagsT
f) = forall a. (Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> IO a
bf2 (\Ptr BF
res Ptr BF
inp -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status
bf_sqrt Ptr BF
res Ptr BF
inp LimbT
p FlagsT
f)

-- | Round to the nearest float matching the configuration parameters.
fround :: BFOpts -> BF -> IO Status
fround :: BFOpts -> BF -> IO Status
fround (BFOpts LimbT
p FlagsT
f) = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (\Ptr BF
ptr -> Ptr BF -> LimbT -> FlagsT -> IO Status
bf_round Ptr BF
ptr LimbT
p FlagsT
f)

-- | Round to the neareset integer.
frint :: RoundMode -> BF -> IO Status
frint :: RoundMode -> BF -> IO Status
frint (RoundMode FlagsT
r) = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (\Ptr BF
ptr -> Ptr BF -> CInt -> IO Status
bf_rint Ptr BF
ptr (forall a b. (Integral a, Num b) => a -> b
fromIntegral FlagsT
r :: CInt))

-- | Exponentiate the first number by the second,
-- and store the result in the third number.
fpow :: BFOpts -> BF -> BF -> BF -> IO Status
fpow :: BFOpts -> BF -> BF -> BF -> IO Status
fpow (BFOpts LimbT
prec FlagsT
flags) = forall a.
(Ptr BF -> Ptr BF -> Ptr BF -> IO a) -> BF -> BF -> BF -> IO a
bf3 (\Ptr BF
out Ptr BF
in1 Ptr BF
in2 -> Ptr BF -> Ptr BF -> Ptr BF -> LimbT -> FlagsT -> IO Status
bf_pow Ptr BF
out Ptr BF
in1 Ptr BF
in2 LimbT
prec FlagsT
flags)





--------------------------------------------------------------------------------
-- export

foreign import ccall "bf_get_float64"
  bf_get_float64 :: Ptr BF -> Ptr Double -> RoundMode -> IO Status

-- | Get the current value of a 'BF' as a Haskell `Double`.
toDouble :: RoundMode -> BF -> IO (Double, Status)
toDouble :: RoundMode -> BF -> IO (Double, Status)
toDouble RoundMode
r = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (\Ptr BF
inp ->
  forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca (\Ptr Double
out ->
   do Status
s <- Ptr BF -> Ptr Double -> RoundMode -> IO Status
bf_get_float64 Ptr BF
inp Ptr Double
out RoundMode
r
      Double
d <- forall a. Storable a => Ptr a -> IO a
peek Ptr Double
out
      forall (f :: * -> *) a. Applicative f => a -> f a
pure (Double
d, Status
s)
  ))


foreign import ccall "bf_atof"
  bf_atof ::
    Ptr BF -> CString -> Ptr CString -> CInt -> LimbT -> FlagsT -> IO CInt


{- | Set the value to the float parsed out of the given string.
  * The radix should not exceed 'LibBF.Opts.maxRadix'.
  * Sets the number to @NaN@ on failure.
  * Assumes that characters are encoded with a single byte each.
  * Retruns:
      - Status for the conversion
      - How many bytes we consumed
      - Did we consume the whole input
-}
setString :: Int -> BFOpts -> String -> BF -> IO (Status,Int,Bool)
setString :: Int -> BFOpts -> String -> BF -> IO (Status, Int, Bool)
setString Int
radix (BFOpts LimbT
prec FlagsT
flags) String
inStr =
  forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1    \Ptr BF
bfPtr ->
  forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca \Ptr CString
nextPtr ->
  forall a. String -> (CString -> IO a) -> IO a
withCAString String
inStr \CString
strPtr ->
  do CInt
stat <- Ptr BF
-> CString -> Ptr CString -> CInt -> LimbT -> FlagsT -> IO CInt
bf_atof Ptr BF
bfPtr CString
strPtr Ptr CString
nextPtr (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
radix) LimbT
prec FlagsT
flags
     CString
next <- forall a. Storable a => Ptr a -> IO a
peek Ptr CString
nextPtr
     let consumed :: Int
consumed = CString
next forall a b. Ptr a -> Ptr b -> Int
`minusPtr` CString
strPtr
         usedAll :: Bool
usedAll = forall (t :: * -> *) a. Foldable t => t a -> Int
length String
inStr forall a. Eq a => a -> a -> Bool
== Int
consumed
     Int
consumed seq :: forall a b. a -> b -> b
`seq` Bool
usedAll seq :: forall a b. a -> b -> b
`seq` forall (f :: * -> *) a. Applicative f => a -> f a
pure (CInt -> Status
Status CInt
stat, Int
consumed, Bool
usedAll)


foreign import ccall "bf_ftoa"
  bf_ftoa :: Ptr CSize -> Ptr BF -> CInt -> LimbT -> FlagsT -> IO CString

-- | Render a big-float as a Haskell string.
-- The radix should not exceed 'LibBF.Opts.maxRadix'.
toString :: Int -> ShowFmt -> BF -> IO String
toString :: Int -> ShowFmt -> BF -> IO String
toString Int
radix (ShowFmt LimbT
ds FlagsT
flags) =
  forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 \Ptr BF
inp ->
  forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca \Ptr CSize
out ->
  do CString
ptr <- Ptr CSize -> Ptr BF -> CInt -> LimbT -> FlagsT -> IO CString
bf_ftoa Ptr CSize
out Ptr BF
inp (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
radix) LimbT
ds FlagsT
flags
     CSize
len <- forall a. Storable a => Ptr a -> IO a
peek Ptr CSize
out
     if CSize
len forall a. Ord a => a -> a -> Bool
> CSize
0
       then
         do String
res <- CString -> IO String
peekCString CString
ptr
            forall a. Ptr a -> IO ()
free CString
ptr
            forall (f :: * -> *) a. Applicative f => a -> f a
pure String
res
       else forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"(error)" -- XXX: throw an exception


-- | An explicit representation for big nums.
data BFRep  = BFRep !Sign !BFNum    -- ^ A signed number
            | BFNaN                 -- ^ Not a number
              deriving (Typeable BFRep
BFRep -> DataType
BFRep -> Constr
(forall b. Data b => b -> b) -> BFRep -> BFRep
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> BFRep -> u
forall u. (forall d. Data d => d -> u) -> BFRep -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> BFRep -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> BFRep -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BFRep -> m BFRep
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BFRep -> m BFRep
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BFRep
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BFRep -> c BFRep
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BFRep)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c BFRep)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BFRep -> m BFRep
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BFRep -> m BFRep
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BFRep -> m BFRep
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BFRep -> m BFRep
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BFRep -> m BFRep
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BFRep -> m BFRep
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> BFRep -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> BFRep -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> BFRep -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> BFRep -> [u]
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> BFRep -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> BFRep -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> BFRep -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> BFRep -> r
gmapT :: (forall b. Data b => b -> b) -> BFRep -> BFRep
$cgmapT :: (forall b. Data b => b -> b) -> BFRep -> BFRep
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c BFRep)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c BFRep)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BFRep)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BFRep)
dataTypeOf :: BFRep -> DataType
$cdataTypeOf :: BFRep -> DataType
toConstr :: BFRep -> Constr
$ctoConstr :: BFRep -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BFRep
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BFRep
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BFRep -> c BFRep
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BFRep -> c BFRep
Data,BFRep -> BFRep -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BFRep -> BFRep -> Bool
$c/= :: BFRep -> BFRep -> Bool
== :: BFRep -> BFRep -> Bool
$c== :: BFRep -> BFRep -> Bool
Eq,Eq BFRep
BFRep -> BFRep -> Bool
BFRep -> BFRep -> Ordering
BFRep -> BFRep -> BFRep
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: BFRep -> BFRep -> BFRep
$cmin :: BFRep -> BFRep -> BFRep
max :: BFRep -> BFRep -> BFRep
$cmax :: BFRep -> BFRep -> BFRep
>= :: BFRep -> BFRep -> Bool
$c>= :: BFRep -> BFRep -> Bool
> :: BFRep -> BFRep -> Bool
$c> :: BFRep -> BFRep -> Bool
<= :: BFRep -> BFRep -> Bool
$c<= :: BFRep -> BFRep -> Bool
< :: BFRep -> BFRep -> Bool
$c< :: BFRep -> BFRep -> Bool
compare :: BFRep -> BFRep -> Ordering
$ccompare :: BFRep -> BFRep -> Ordering
Ord,Int -> BFRep -> ShowS
[BFRep] -> ShowS
BFRep -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BFRep] -> ShowS
$cshowList :: [BFRep] -> ShowS
show :: BFRep -> String
$cshow :: BFRep -> String
showsPrec :: Int -> BFRep -> ShowS
$cshowsPrec :: Int -> BFRep -> ShowS
Show)

instance Hashable BFRep where
  hashWithSalt :: Int -> BFRep -> Int
hashWithSalt Int
s BFRep
BFNaN           = Int
s forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
0::Int)
  hashWithSalt Int
s (BFRep Sign
Pos BFNum
num) = Int
s forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
1::Int) forall a. Hashable a => Int -> a -> Int
`hashWithSalt` BFNum
num
  hashWithSalt Int
s (BFRep Sign
Neg BFNum
num) = Int
s forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
2::Int) forall a. Hashable a => Int -> a -> Int
`hashWithSalt` BFNum
num

-- | Representations for unsigned floating point numbers.
data BFNum  = Zero                 -- ^ zero
            | Num Integer !Int64   -- ^ @x * 2 ^ y@
            | Inf                  -- ^ infinity
              deriving (Typeable BFNum
BFNum -> DataType
BFNum -> Constr
(forall b. Data b => b -> b) -> BFNum -> BFNum
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> BFNum -> u
forall u. (forall d. Data d => d -> u) -> BFNum -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> BFNum -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> BFNum -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BFNum -> m BFNum
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BFNum -> m BFNum
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BFNum
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BFNum -> c BFNum
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BFNum)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c BFNum)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BFNum -> m BFNum
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BFNum -> m BFNum
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BFNum -> m BFNum
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BFNum -> m BFNum
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BFNum -> m BFNum
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BFNum -> m BFNum
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> BFNum -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> BFNum -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> BFNum -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> BFNum -> [u]
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> BFNum -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> BFNum -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> BFNum -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> BFNum -> r
gmapT :: (forall b. Data b => b -> b) -> BFNum -> BFNum
$cgmapT :: (forall b. Data b => b -> b) -> BFNum -> BFNum
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c BFNum)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c BFNum)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BFNum)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BFNum)
dataTypeOf :: BFNum -> DataType
$cdataTypeOf :: BFNum -> DataType
toConstr :: BFNum -> Constr
$ctoConstr :: BFNum -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BFNum
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BFNum
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BFNum -> c BFNum
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BFNum -> c BFNum
Data,BFNum -> BFNum -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BFNum -> BFNum -> Bool
$c/= :: BFNum -> BFNum -> Bool
== :: BFNum -> BFNum -> Bool
$c== :: BFNum -> BFNum -> Bool
Eq,Eq BFNum
BFNum -> BFNum -> Bool
BFNum -> BFNum -> Ordering
BFNum -> BFNum -> BFNum
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: BFNum -> BFNum -> BFNum
$cmin :: BFNum -> BFNum -> BFNum
max :: BFNum -> BFNum -> BFNum
$cmax :: BFNum -> BFNum -> BFNum
>= :: BFNum -> BFNum -> Bool
$c>= :: BFNum -> BFNum -> Bool
> :: BFNum -> BFNum -> Bool
$c> :: BFNum -> BFNum -> Bool
<= :: BFNum -> BFNum -> Bool
$c<= :: BFNum -> BFNum -> Bool
< :: BFNum -> BFNum -> Bool
$c< :: BFNum -> BFNum -> Bool
compare :: BFNum -> BFNum -> Ordering
$ccompare :: BFNum -> BFNum -> Ordering
Ord,Int -> BFNum -> ShowS
[BFNum] -> ShowS
BFNum -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BFNum] -> ShowS
$cshowList :: [BFNum] -> ShowS
show :: BFNum -> String
$cshow :: BFNum -> String
showsPrec :: Int -> BFNum -> ShowS
$cshowsPrec :: Int -> BFNum -> ShowS
Show)

instance Hashable BFNum where
  hashWithSalt :: Int -> BFNum -> Int
hashWithSalt Int
s BFNum
Zero         = Int
s forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
0::Int)
  hashWithSalt Int
s (Num Integer
mag SLimbT
ex) = Int
s forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
1::Int) forall a. Hashable a => Int -> a -> Int
`hashWithSalt` Integer
mag forall a. Hashable a => Int -> a -> Int
`hashWithSalt` SLimbT
ex
  hashWithSalt Int
s BFNum
Inf          = Int
s forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
2::Int)

-- | Returns 'Nothing' for @NaN@.
getSign :: BF -> IO (Maybe Sign)
getSign :: BF -> IO (Maybe Sign)
getSign = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (\Ptr BF
ptr ->
  do SLimbT
e <- (\Ptr BF
hsc_ptr -> forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr BF
hsc_ptr Int
16) Ptr BF
ptr
{-# LINE 580 "src/LibBF/Mutable.hsc" #-}
     if (e :: SLimbT) == 9223372036854775807
{-# LINE 581 "src/LibBF/Mutable.hsc" #-}
        then pure Nothing
        else (Just . asSign) <$> (\hsc_ptr -> peekByteOff hsc_ptr 8) ptr)
{-# LINE 583 "src/LibBF/Mutable.hsc" #-}

-- | Get the exponent of the number.
-- Returns 'Nothing' for inifinity, zero and NaN.
getExp :: BF -> IO (Maybe Int64)
getExp :: BF -> IO (Maybe SLimbT)
getExp = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (\Ptr BF
ptr ->
  do SLimbT
e <- (\Ptr BF
hsc_ptr -> forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr BF
hsc_ptr Int
16) Ptr BF
ptr
{-# LINE 589 "src/LibBF/Mutable.hsc" #-}
     pure $! if (e :: SLimbT) < 9223372036854775806 &&
{-# LINE 590 "src/LibBF/Mutable.hsc" #-}
                e > -9223372036854775808 then Just (fromIntegral e)
{-# LINE 591 "src/LibBF/Mutable.hsc" #-}
                                         else Nothing)

{-| Check if the given numer is infinite. -}
isInf :: BF -> IO Bool
isInf :: BF -> IO Bool
isInf = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (\Ptr BF
ptr ->
  do SLimbT
e <- (\Ptr BF
hsc_ptr -> forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr BF
hsc_ptr Int
16) Ptr BF
ptr
{-# LINE 597 "src/LibBF/Mutable.hsc" #-}
     if | (e :: SLimbT) == 9223372036854775806 -> pure True
{-# LINE 598 "src/LibBF/Mutable.hsc" #-}
        | otherwise -> pure False)

-- | Get the representation of the number.
toRep :: BF -> IO BFRep
toRep :: BF -> IO BFRep
toRep = forall a. (Ptr BF -> IO a) -> BF -> IO a
bf1 (\Ptr BF
ptr ->
  do CInt
s <- (\Ptr BF
hsc_ptr -> forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr BF
hsc_ptr Int
8) Ptr BF
ptr
{-# LINE 604 "src/LibBF/Mutable.hsc" #-}
     let sgn = if asBool s then Neg else Pos
     SLimbT
e <- (\Ptr BF
hsc_ptr -> forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr BF
hsc_ptr Int
16) Ptr BF
ptr
{-# LINE 606 "src/LibBF/Mutable.hsc" #-}
     if | e == 9223372036854775807  -> pure BFNaN
{-# LINE 607 "src/LibBF/Mutable.hsc" #-}
        | e == 9223372036854775806  -> pure (BFRep sgn Inf)
{-# LINE 608 "src/LibBF/Mutable.hsc" #-}
        | e == -9223372036854775808 -> pure (BFRep sgn Zero)
{-# LINE 609 "src/LibBF/Mutable.hsc" #-}
        | otherwise ->
        do l <- (\hsc_ptr -> peekByteOff hsc_ptr 24)  ptr
{-# LINE 611 "src/LibBF/Mutable.hsc" #-}
           p <- (\hsc_ptr -> peekByteOff hsc_ptr 32)  ptr
{-# LINE 612 "src/LibBF/Mutable.hsc" #-}
           let len = fromIntegral (l :: Word64) :: Int
               -- This should not really limit precision as it counts
               -- number of Word64s (not bytes)

               step x i = do w <- peekElemOff p i
                             pure ((x `shiftL` 64) + fromIntegral (w :: Word64))

           base <- foldM step 0 (reverse (take len [ 0 .. ]))
           let bias = 64 * fromIntegral len
               norm bs bi
                 | even bs    = norm (bs `shiftR` 1) (bi - 1)
                 | otherwise  = BFRep sgn (Num bs (e - bi))

           pure (norm base bias) -- (BFRep sgn (Num base (e - bias)))
  )