module Data.Double.Conversion
(
toExponential
, toFixed
, toPrecision
, toShortest
) where
import Control.Monad (when)
import Control.Monad.ST (unsafeIOToST, runST)
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_ToExponential val mba (fromIntegral ndigits)
where len = c_ToExponentialLength
toFixed :: Int -> Double -> Text
toFixed ndigits = convert "toFixed" len $ \val mba ->
c_ToFixed val mba (fromIntegral ndigits)
where len = c_ToFixedLength
toShortest :: Double -> Text
toShortest = convert "toShortest" len c_ToShortest
where len = c_ToShortestLength
toPrecision :: Int -> Double -> Text
toPrecision ndigits = convert "toPrecision" len $ \val mba ->
c_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." ++ func ++
": conversion failed (invalid precision requested)"
frozen <- A.unsafeFreeze buf
return $ Text frozen 0 (fromIntegral size)
foreign import ccall unsafe "hs-double-conversion.h _hs_ToShortestLength"
c_ToShortestLength :: CInt
foreign import ccall unsafe "hs-double-conversion.h _hs_ToShortest"
c_ToShortest :: CDouble -> MutableByteArray# s -> IO CInt
foreign import ccall unsafe "hs-double-conversion.h _hs_ToFixedLength"
c_ToFixedLength :: CInt
foreign import ccall unsafe "hs-double-conversion.h _hs_ToFixed"
c_ToFixed :: CDouble -> MutableByteArray# s -> CInt -> IO CInt
foreign import ccall unsafe "hs-double-conversion.h _hs_ToExponentialLength"
c_ToExponentialLength :: CInt
foreign import ccall unsafe "hs-double-conversion.h _hs_ToExponential"
c_ToExponential :: CDouble -> MutableByteArray# s -> CInt -> IO CInt
foreign import ccall unsafe "hs-double-conversion.h _hs_ToPrecisionLength"
c_ToPrecisionLength :: CInt
foreign import ccall unsafe "hs-double-conversion.h _hs_ToPrecision"
c_ToPrecision :: CDouble -> MutableByteArray# s -> CInt -> IO CInt