module Data.Double.Conversion.Text
(
toExponential
, toFixed
, toPrecision
, toShortest
) where
import Control.Monad (when)
import Control.Monad.ST (unsafeIOToST, 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 ndigits = convert "toExponential" len $ \val mba ->
c_Text_ToExponential val mba (fromIntegral ndigits)
where len = c_ToExponentialLength
toFixed :: Int -> Double -> Text
toFixed ndigits = convert "toFixed" len $ \val mba ->
c_Text_ToFixed val mba (fromIntegral ndigits)
where len = c_ToFixedLength
toShortest :: Double -> Text
toShortest = convert "toShortest" len c_Text_ToShortest
where len = c_ToShortestLength
toPrecision :: Int -> Double -> Text
toPrecision ndigits = convert "toPrecision" len $ \val mba ->
c_Text_ToPrecision val mba (fromIntegral ndigits)
where len = c_ToPrecisionLength
convert :: String -> CInt
-> (forall s. CDouble -> MutableByteArray# s -> IO CInt)
-> Double -> Text
convert func len act val = runST go
where
go = do
buf <- A.new (fromIntegral len)
size <- unsafeIOToST $ act (realToFrac val) (A.maBA buf)
when (size == 1) .
fail $ "Data.Double.Conversion.Text." ++ func ++
": conversion failed (invalid precision requested)"
frozen <- A.unsafeFreeze buf
return $ Text frozen 0 (fromIntegral size)