{-# LANGUAGE CPP, MagicHash, Rank2Types #-}
module Data.Double.Conversion.Text
(
toExponential
, toFixed
, toPrecision
, toShortest
) where
import Control.Monad (when)
#if MIN_VERSION_base(4,4,0)
import Control.Monad.ST.Unsafe (unsafeIOToST)
#else
import Control.Monad.ST (unsafeIOToST)
#endif
import Control.Monad.ST (runST)
import Data.Double.Conversion.FFI
import Data.Text.Internal (Text(Text))
import Foreign.C.Types (CDouble, CInt)
import GHC.Prim (MutableByteArray#)
import qualified Data.Text.Array as A
toExponential :: Int -> Double -> Text
toExponential :: Int -> Double -> Text
toExponential ndigits :: Int
ndigits = String
-> CInt
-> (forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double
-> Text
convert "toExponential" CInt
len ((forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double -> Text)
-> (forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double
-> Text
forall a b. (a -> b) -> a -> b
$ \val :: CDouble
val mba :: MutableByteArray# s
mba ->
CDouble -> MutableByteArray# s -> CInt -> IO CInt
forall s. CDouble -> MutableByteArray# s -> CInt -> IO CInt
c_Text_ToExponential CDouble
val MutableByteArray# s
mba (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ndigits)
where len :: CInt
len = CInt
c_ToExponentialLength
{-# NOINLINE len #-}
toFixed :: Int -> Double -> Text
toFixed :: Int -> Double -> Text
toFixed ndigits :: Int
ndigits = String
-> CInt
-> (forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double
-> Text
convert "toFixed" CInt
len ((forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double -> Text)
-> (forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double
-> Text
forall a b. (a -> b) -> a -> b
$ \val :: CDouble
val mba :: MutableByteArray# s
mba ->
CDouble -> MutableByteArray# s -> CInt -> IO CInt
forall s. CDouble -> MutableByteArray# s -> CInt -> IO CInt
c_Text_ToFixed CDouble
val MutableByteArray# s
mba (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ndigits)
where len :: CInt
len = CInt
c_ToFixedLength
{-# NOINLINE len #-}
toShortest :: Double -> Text
toShortest :: Double -> Text
toShortest = String
-> CInt
-> (forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double
-> Text
convert "toShortest" CInt
len forall s. CDouble -> MutableByteArray# s -> IO CInt
c_Text_ToShortest
where len :: CInt
len = CInt
c_ToShortestLength
{-# NOINLINE len #-}
toPrecision :: Int -> Double -> Text
toPrecision :: Int -> Double -> Text
toPrecision ndigits :: Int
ndigits = String
-> CInt
-> (forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double
-> Text
convert "toPrecision" CInt
len ((forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double -> Text)
-> (forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double
-> Text
forall a b. (a -> b) -> a -> b
$ \val :: CDouble
val mba :: MutableByteArray# s
mba ->
CDouble -> MutableByteArray# s -> CInt -> IO CInt
forall s. CDouble -> MutableByteArray# s -> CInt -> IO CInt
c_Text_ToPrecision CDouble
val MutableByteArray# s
mba (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ndigits)
where len :: CInt
len = CInt
c_ToPrecisionLength
{-# NOINLINE len #-}
convert :: String -> CInt
-> (forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double -> Text
convert :: String
-> CInt
-> (forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double
-> Text
convert func :: String
func len :: CInt
len act :: forall s. CDouble -> MutableByteArray# s -> IO CInt
act val :: Double
val = (forall s. ST s Text) -> Text
forall a. (forall s. ST s a) -> a
runST forall s. ST s Text
go
where
go :: ST s Text
go = do
MArray s
buf <- Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.new (CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
len)
CInt
size <- IO CInt -> ST s CInt
forall a s. IO a -> ST s a
unsafeIOToST (IO CInt -> ST s CInt) -> IO CInt -> ST s CInt
forall a b. (a -> b) -> a -> b
$ CDouble -> MutableByteArray# s -> IO CInt
forall s. CDouble -> MutableByteArray# s -> IO CInt
act (Double -> CDouble
forall a b. (Real a, Fractional b) => a -> b
realToFrac Double
val) (MArray s -> MutableByteArray# s
forall s. MArray s -> MutableByteArray# s
A.maBA MArray s
buf)
Bool -> ST s () -> ST s ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
size CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== -1) (ST s () -> ST s ()) -> (String -> ST s ()) -> String -> ST s ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
String -> ST s ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> ST s ()) -> String -> ST s ()
forall a b. (a -> b) -> a -> b
$ "Data.Double.Conversion.Text." String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
func String -> String -> String
forall a. [a] -> [a] -> [a]
++
": conversion failed (invalid precision requested)"
Array
frozen <- MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
buf
Text -> ST s Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
frozen 0 (CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
size)