packages feed

double-conversion 2.0.2.0 → 2.0.5.0

raw patch · 35 files changed

Files

Data/Double/Conversion/ByteString.hs view
@@ -7,6 +7,13 @@ -- Stability   : experimental -- Portability : GHC --+-- This module left now only for compatibility and should not be used+-- in new projects. +-- Please, use Convertable type class from Data.Double.Conversion.Convertable+-- +-- It is espesially recommended to convert a large amount of numbers via bytestring builder+-- using methods of Convertable type class. It is about 10-15x faster. +--  -- Fast, efficient support for converting between double precision -- floating point values and text. --@@ -23,54 +30,27 @@     , toShortest     ) where -import Control.Monad (when)-import Foreign.ForeignPtr (withForeignPtr)-import Data.Double.Conversion.FFI-import Data.Word (Word8)-import Data.ByteString.Internal (ByteString(..), mallocByteString)-import Foreign.C.Types (CDouble, CInt)-import Foreign.Ptr (Ptr)-import System.IO.Unsafe (unsafePerformIO)+import qualified Data.Double.Conversion.Convertable+import Data.ByteString.Internal  -- | Compute a representation in exponential format with the requested -- number of digits after the decimal point. The last emitted digit is -- rounded.  If -1 digits are requested, then the shortest exponential -- representation is computed. toExponential :: Int -> Double -> ByteString-toExponential ndigits = convert "toExponential" len $ \val mba ->-                        c_ToExponential val mba (fromIntegral ndigits)-  where len = c_ToExponentialLength-        {-# NOINLINE len #-}+toExponential = Data.Double.Conversion.Convertable.toExponential  -- | Compute a decimal representation with a fixed number of digits -- after the decimal point. The last emitted digit is rounded. toFixed :: Int -> Double -> ByteString-toFixed ndigits = convert "toFixed" len $ \val mba ->-                  c_ToFixed val mba (fromIntegral ndigits)-  where len = c_ToFixedLength-        {-# NOINLINE len #-}+toFixed = Data.Double.Conversion.Convertable.toFixed  -- | Compute the shortest string of digits that correctly represent -- the input number. toShortest :: Double -> ByteString-toShortest = convert "toShortest" len c_ToShortest-  where len = c_ToShortestLength-        {-# NOINLINE len #-}+toShortest = Data.Double.Conversion.Convertable.toShortest  -- | Compute @precision@ leading digits of the given value either in -- exponential or decimal format. The last computed digit is rounded. toPrecision :: Int -> Double -> ByteString-toPrecision ndigits = convert "toPrecision" len $ \val mba ->-                      c_ToPrecision val mba (fromIntegral ndigits)-  where len = c_ToPrecisionLength-        {-# NOINLINE len #-}--convert :: String -> CInt -> (CDouble -> Ptr Word8 -> IO CInt)-        -> Double -> ByteString-convert func len act val = unsafePerformIO $ do-  fp <- mallocByteString (fromIntegral len)-  size <- withForeignPtr fp $ act (realToFrac val)-  when (size == -1) .-    fail $ "Data.Double.Conversion.ByteString." ++ func ++-           ": conversion failed (invalid precision requested)"-  return $ PS fp 0 (fromIntegral size)+toPrecision = Data.Double.Conversion.Convertable.toPrecision
+ Data/Double/Conversion/Convertable.hs view
@@ -0,0 +1,296 @@+{-# LANGUAGE DefaultSignatures, InstanceSigs, MagicHash, MultiParamTypeClasses,+             TypeFamilies, TypeOperators #-}++-- |+-- Module      : Data.Double.Conversion.Convertable+-- Copyright   : (c) 2011 MailRank, Inc.+--+-- License     : BSD-style+-- Maintainer  : bos@serpentine.com+-- Stability   : experimental+-- Portability : GHC++module Data.Double.Conversion.Convertable+    ( Convertable(..)+    ) where+import Data.ByteString.Builder.Prim (primBounded)+import Data.Text (Text)++import Data.Double.Conversion.Internal.FFI+import Data.String (IsString)++import qualified Data.ByteString.Builder as BB (Builder)+import qualified Data.ByteString.Internal as B (ByteString(..))+import qualified Data.Double.Conversion.Internal.ByteString as CB (convert)+import qualified Data.Double.Conversion.Internal.ByteStringBuilder as CBB (convert)+import qualified Data.Double.Conversion.Internal.Text as CT (convert)+import qualified Data.Double.Conversion.Internal.TextBuilder as CTB (convert)+import qualified Data.Text.Internal.Builder as T (Builder)++-- | Type class for floating data types, that can be converted, using double-conversion library+--+-- Default instanced convert input to Double and then make Bytestring Builder from it.+--+-- list of functions :+--+-- toExponential:+-- Compute a representation in exponential format with the requested+-- number of digits after the decimal point. The last emitted digit is+-- rounded.  If -1 digits are requested, then the shortest exponential+-- representation is computed.+--+-- toPrecision:+-- Compute @precision@ leading digits of the given value either in+-- exponential or decimal format. The last computed digit is rounded.+--+-- toFixed:+-- Compute a decimal representation with a fixed number of digits+-- after the decimal point. The last emitted digit is rounded.+--+-- toShortest:+-- Compute the shortest string of digits that correctly represent+-- the input number.+--+-- Conversion to text via Builder (both in the in case of bytestring and text) in case of single number+-- is a bit slower, than to text or bytestring directly.+-- But conversion a large amount of numbers to text via Builder (for example using foldr) is much faster than direct conversion to Text (up to 10-15x).+--+-- The same works for bytestrings: conversion, for example, a list of 20000 doubles to bytestring builder +-- and then to bytestring is about 13 times faster than direct conversion of this list to bytestring. +--+-- Conversion to text via text builder is a little bit slower, than conversion to bytestring via bytestring builder. +++class (RealFloat a, IsString b) => Convertable a b where+  toExponential :: Int -> a -> b+  default toExponential :: (b ~ BB.Builder) => Int -> a -> b+  toExponential ndigits num = primBounded (CBB.convert "toExponential" len $ \val mba ->+                        c_ToExponential val mba (fromIntegral ndigits)) (realToFrac num :: Double)+      where len = c_ToExponentialLength+            {-# NOINLINE len #-}++  toPrecision :: Int -> a -> b+  default toPrecision :: (b ~ BB.Builder) => Int -> a -> b+  toPrecision ndigits num = primBounded (CBB.convert "toPrecision" len $ \val mba ->+                      c_ToPrecision val mba (fromIntegral ndigits)) (realToFrac num :: Double)+      where len = c_ToPrecisionLength+            {-# NOINLINE len #-}++  toFixed :: Int -> a -> b+  default toFixed :: (b ~ BB.Builder) => Int -> a -> b+  toFixed ndigits num = primBounded (CBB.convert "toFixed" len $ \val mba ->+                  c_ToFixed val mba (fromIntegral ndigits)) (realToFrac num :: Double)+      where len = c_ToFixedLength+            {-# NOINLINE len #-}++  toShortest :: a -> b+  default toShortest :: (b ~ BB.Builder) => a -> b+  toShortest num = primBounded (CBB.convert "toShortest" len c_ToShortest) (realToFrac num :: Double)+      where len = c_ToShortestLength+            {-# NOINLINE len #-}++-- Instances++instance Convertable Double BB.Builder where+    toExponential :: Int -> Double -> BB.Builder+    toExponential ndigits = primBounded $ CBB.convert "toExponential" len $ \val mba ->+                        c_ToExponential val mba (fromIntegral ndigits)+        where len = c_ToExponentialLength+              {-# NOINLINE len #-}++    toPrecision :: Int -> Double -> BB.Builder+    toPrecision ndigits = primBounded (CBB.convert "toPrecision" len $ \val mba ->+                      c_ToPrecision val mba (fromIntegral ndigits))+        where len = c_ToPrecisionLength+              {-# NOINLINE len #-}++    toShortest :: Double -> BB.Builder+    toShortest = primBounded $ CBB.convert "toShortest" len c_ToShortest+        where len = c_ToShortestLength+              {-# NOINLINE len #-}++    toFixed :: Int -> Double -> BB.Builder+    toFixed ndigits = primBounded $ CBB.convert "toFixed" len $ \val mba ->+                  c_ToFixed val mba (fromIntegral ndigits)+        where len = c_ToFixedLength+              {-# NOINLINE len #-}+++instance Convertable Float BB.Builder where+    toExponential :: Int -> Float -> BB.Builder+    toExponential ndigits = primBounded $ CBB.convert "toExponential" len $ \val mba ->+                        c_ToExponentialFloat val mba (fromIntegral ndigits)+        where len = c_ToExponentialLength+              {-# NOINLINE len #-}++    toPrecision :: Int -> Float -> BB.Builder+    toPrecision ndigits = primBounded (CBB.convert "toPrecision" len $ \val mba ->+                      c_ToPrecisionFloat val mba (fromIntegral ndigits))+        where len = c_ToPrecisionLength+              {-# NOINLINE len #-}++    toShortest :: Float -> BB.Builder+    toShortest = primBounded $ CBB.convert "toShortest" len c_ToShortestFloat+        where len = c_ToShortestLength+              {-# NOINLINE len #-}++    toFixed :: Int -> Float -> BB.Builder+    toFixed ndigits = primBounded $ CBB.convert "toFixed" len $ \val mba ->+                  c_ToFixedFloat val mba (fromIntegral ndigits)+        where len = c_ToFixedLength+              {-# NOINLINE len #-}++-- Fast conversion to bytestring.+-- Although about 15 times faster than plain 'show', these functions+-- are /slower/ than their 'Text' counterparts, at roughly half the+-- speed.  (This seems to be due to the cost of allocating+-- 'ByteString' values via @malloc@.)++instance Convertable Double B.ByteString where+    toExponential :: Int -> Double -> B.ByteString+    toExponential ndigits = CB.convert "toExponential" len $ \val mba ->+                        c_ToExponential val mba (fromIntegral ndigits)+        where len = c_ToExponentialLength+              {-# NOINLINE len #-}++    toFixed :: Int -> Double -> B.ByteString+    toFixed ndigits = CB.convert "toFixed" len $ \val mba ->+                  c_ToFixed val mba (fromIntegral ndigits)+        where len = c_ToFixedLength+              {-# NOINLINE len #-}++    toShortest :: Double -> B.ByteString+    toShortest = CB.convert "toShortest" len c_ToShortest+        where len = c_ToShortestLength+              {-# NOINLINE len #-}++    toPrecision :: Int -> Double -> B.ByteString+    toPrecision ndigits = CB.convert "toPrecision" len $ \val mba ->+                      c_ToPrecision val mba (fromIntegral ndigits)+        where len = c_ToPrecisionLength+              {-# NOINLINE len #-}+++instance Convertable Float B.ByteString where+    toExponential :: Int -> Float -> B.ByteString+    toExponential ndigits = CB.convert "toExponential" len $ \val mba ->+                        c_ToExponentialFloat val mba (fromIntegral ndigits)+        where len = c_ToExponentialLength+              {-# NOINLINE len #-}++    toFixed :: Int -> Float -> B.ByteString+    toFixed ndigits = CB.convert "toFixed" len $ \val mba ->+                  c_ToFixedFloat val mba (fromIntegral ndigits)+        where len = c_ToFixedLength+              {-# NOINLINE len #-}++    toShortest :: Float -> B.ByteString+    toShortest = CB.convert "toShortest" len c_ToShortestFloat+        where len = c_ToShortestLength+              {-# NOINLINE len #-}++    toPrecision :: Int -> Float -> B.ByteString+    toPrecision ndigits = CB.convert "toPrecision" len $ \val mba ->+                      c_ToPrecisionFloat val mba (fromIntegral ndigits)+        where len = c_ToPrecisionLength+              {-# NOINLINE len #-}+++instance Convertable Double Text where+    toExponential :: Int -> Double -> Text+    toExponential ndigits = CT.convert "toExponential" len $ \val mba ->+                            c_Text_ToExponential val mba (fromIntegral ndigits)+        where len = c_ToExponentialLength+              {-# NOINLINE len #-}++    toFixed :: Int -> Double -> Text+    toFixed ndigits = CT.convert "toFixed" len $ \val mba ->+                    c_Text_ToFixed val mba (fromIntegral ndigits)+        where len = c_ToFixedLength+              {-# NOINLINE len #-}++    toShortest :: Double -> Text+    toShortest = CT.convert "toShortest" len c_Text_ToShortest+        where len = c_ToShortestLength+              {-# NOINLINE len #-}++    toPrecision :: Int -> Double -> Text+    toPrecision ndigits = CT.convert "toPrecision" len $ \val mba ->+                          c_Text_ToPrecision val mba (fromIntegral ndigits)+        where len = c_ToPrecisionLength+              {-# NOINLINE len #-}+++instance Convertable Float Text where+    toExponential :: Int -> Float -> Text+    toExponential ndigits = CT.convert "toExponential" len $ \val mba ->+                            c_Text_ToExponentialFloat val mba (fromIntegral ndigits)+        where len = c_ToExponentialLength+              {-# NOINLINE len #-}++    toFixed :: Int -> Float -> Text+    toFixed ndigits = CT.convert "toFixed" len $ \val mba ->+                    c_Text_ToFixedFloat val mba (fromIntegral ndigits)+        where len = c_ToFixedLength+              {-# NOINLINE len #-}++    toShortest :: Float -> Text+    toShortest = CT.convert "toShortest" len c_Text_ToShortestFloat+        where len = c_ToShortestLength+              {-# NOINLINE len #-}++    toPrecision :: Int -> Float -> Text+    toPrecision ndigits = CT.convert "toPrecision" len $ \val mba ->+                          c_Text_ToPrecisionFloat val mba (fromIntegral ndigits)+        where len = c_ToPrecisionLength+              {-# NOINLINE len #-}+++instance Convertable Double T.Builder where+    toExponential :: Int -> Double -> T.Builder+    toExponential ndigits = CTB.convert "toExponential" len $ \val mba ->+                            c_Text_ToExponential val mba (fromIntegral ndigits)+        where len = c_ToExponentialLength+              {-# NOINLINE len #-}++    toFixed :: Int -> Double -> T.Builder+    toFixed ndigits = CTB.convert "toFixed" len $ \val mba ->+                      c_Text_ToFixed val mba (fromIntegral ndigits)+        where len = c_ToFixedLength+              {-# NOINLINE len #-}++    toShortest :: Double -> T.Builder+    toShortest = CTB.convert "toShortest" len c_Text_ToShortest+        where len = c_ToShortestLength+              {-# NOINLINE len #-}++    toPrecision :: Int -> Double -> T.Builder+    toPrecision ndigits = CTB.convert "toPrecision" len $ \val mba ->+                          c_Text_ToPrecision val mba (fromIntegral ndigits)+        where len = c_ToPrecisionLength+              {-# NOINLINE len #-}+++instance Convertable Float T.Builder where+    toExponential :: Int -> Float -> T.Builder+    toExponential ndigits = CTB.convert "toExponential" len $ \val mba ->+                            c_Text_ToExponentialFloat val mba (fromIntegral ndigits)+        where len = c_ToExponentialLength+              {-# NOINLINE len #-}++    toFixed :: Int -> Float -> T.Builder+    toFixed ndigits = CTB.convert "toFixed" len $ \val mba ->+                      c_Text_ToFixedFloat val mba (fromIntegral ndigits)+        where len = c_ToFixedLength+              {-# NOINLINE len #-}++    toShortest :: Float -> T.Builder+    toShortest = CTB.convert "toShortest" len c_Text_ToShortestFloat+        where len = c_ToShortestLength+              {-# NOINLINE len #-}++    toPrecision :: Int -> Float -> T.Builder+    toPrecision ndigits = CTB.convert "toPrecision" len $ \val mba ->+                          c_Text_ToPrecisionFloat val mba (fromIntegral ndigits)+        where len = c_ToPrecisionLength+              {-# NOINLINE len #-}
− Data/Double/Conversion/FFI.hs
@@ -1,74 +0,0 @@-{-# LANGUAGE CPP, ForeignFunctionInterface, MagicHash, UnliftedFFITypes #-}---- |--- Module      : Data.Double.Conversion.FFI--- Copyright   : (c) 2011 MailRank, Inc.------ License     : BSD-style--- Maintainer  : bos@serpentine.com--- Stability   : experimental--- Portability : GHC------ FFI interface support for converting between double precision--- floating point values and text.--module Data.Double.Conversion.FFI-    (-      c_Text_ToExponential-    , c_Text_ToFixed-    , c_Text_ToPrecision-    , c_Text_ToShortest-    , c_ToExponentialLength-    , c_ToFixedLength-    , c_ToPrecisionLength-    , c_ToShortestLength-    , c_ToExponential-    , c_ToFixed-    , c_ToPrecision-    , c_ToShortest-    ) where--import Data.Word (Word8)-#if __GLASGOW_HASKELL__ >= 703-import Foreign.C.Types (CDouble(CDouble), CInt(CInt))-#else-import Foreign.C.Types (CDouble, CInt)-#endif-import Foreign.Ptr (Ptr)-import GHC.Prim (MutableByteArray#)--foreign import ccall unsafe "hs-double-conversion.h _hs_ToShortestLength"-    c_ToShortestLength :: CInt--foreign import ccall unsafe "hs-double-conversion.h _hs_Text_ToShortest"-    c_Text_ToShortest :: CDouble -> MutableByteArray# s -> IO CInt--foreign import ccall unsafe "hs-double-conversion.h _hs_ToShortest"-    c_ToShortest :: CDouble -> Ptr Word8 -> IO CInt--foreign import ccall unsafe "hs-double-conversion.h _hs_ToFixedLength"-    c_ToFixedLength :: CInt--foreign import ccall unsafe "hs-double-conversion.h _hs_Text_ToFixed"-    c_Text_ToFixed :: CDouble -> MutableByteArray# s -> CInt -> IO CInt--foreign import ccall unsafe "hs-double-conversion.h _hs_ToFixed"-    c_ToFixed :: CDouble -> Ptr Word8 -> 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_Text_ToExponential"-    c_Text_ToExponential :: CDouble -> MutableByteArray# s -> CInt -> IO CInt--foreign import ccall unsafe "hs-double-conversion.h _hs_ToExponential"-    c_ToExponential :: CDouble -> Ptr Word8 -> 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_Text_ToPrecision"-    c_Text_ToPrecision :: CDouble -> MutableByteArray# s -> CInt -> IO CInt--foreign import ccall unsafe "hs-double-conversion.h _hs_ToPrecision"-    c_ToPrecision :: CDouble -> Ptr Word8 -> CInt -> IO CInt
+ Data/Double/Conversion/Internal/ByteString.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE TypeFamilies, TypeOperators #-}++-- |+-- Module      : Data.Double.Conversion.ByteString+-- Copyright   : (c) 2011 MailRank, Inc.+--+-- License     : BSD-style+-- Maintainer  : bos@serpentine.com+-- Stability   : experimental+-- Portability : GHC+--+-- Fast, efficient support for converting between double precision+-- floating point values and text.+--+-- Although about 15 times faster than plain 'show', these functions+-- are /slower/ than their 'Text' counterparts, at roughly half the+-- speed.  (This seems to be due to the cost of allocating+-- 'ByteString' values via @malloc@.)++module Data.Double.Conversion.Internal.ByteString+    ( convert+    ) where++import Control.Monad (when)+import Data.ByteString.Internal (ByteString(..), mallocByteString)+import Data.Double.Conversion.Internal.FFI (ForeignFloating)+import Data.Word (Word8)+import Foreign.C.Types (CDouble, CFloat, CInt)+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Ptr (Ptr)+import System.IO.Unsafe (unsafePerformIO)++convert :: (RealFloat a, RealFloat b , b ~ ForeignFloating a) => String -> CInt -> (b -> Ptr Word8 -> IO CInt)+        -> a -> ByteString+{-# SPECIALIZE convert :: String -> CInt -> (CDouble -> Ptr Word8 -> IO CInt) -> Double -> ByteString #-}+{-# SPECIALIZE convert :: String -> CInt -> (CFloat -> Ptr Word8 -> IO CInt) -> Float -> ByteString #-}+{-# INLINABLE convert #-}+convert func len act val = unsafePerformIO $ do+  fp <- mallocByteString (fromIntegral len)+  size <- withForeignPtr fp $ act (realToFrac val)+  when (size == -1) .+    fail $ "Data.Double.Conversion.ByteString." ++ func +++           ": conversion failed (invalid precision requested)"+  return $ PS fp 0 (fromIntegral size)
+ Data/Double/Conversion/Internal/ByteStringBuilder.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE TypeFamilies, TypeOperators #-}++-- |+-- Module      : Data.Double.Conversion.ByteStringBuilder+-- Copyright   : (c) 2011 MailRank, Inc.+--+-- License     : BSD-style+-- Maintainer  : bos@serpentine.com+-- Stability   : experimental+-- Portability : GHC+--+-- Fast, efficient support for converting between double precision+-- floating point values and bytestring builder.++module Data.Double.Conversion.Internal.ByteStringBuilder+    (convert+    ) where++import Control.Monad (when)++import Data.ByteString.Builder.Prim.Internal (BoundedPrim, boudedPrim)++import Data.Double.Conversion.Internal.FFI (ForeignFloating)+import Data.Word (Word8)+import Foreign.C.Types (CDouble, CFloat, CInt)+import Foreign.Ptr (Ptr, plusPtr)++convert :: (RealFloat a, RealFloat b , b ~ ForeignFloating a) => String -> CInt -> (b -> Ptr Word8 -> IO CInt) -> BoundedPrim a+{-# SPECIALIZE convert :: String -> CInt -> (CDouble -> Ptr Word8 -> IO CInt) -> BoundedPrim Double #-}+{-# SPECIALIZE convert :: String -> CInt -> (CFloat -> Ptr Word8 -> IO CInt) -> BoundedPrim Float #-}+{-# INLINABLE convert #-}+convert func len act = boudedPrim (fromIntegral len) $ \val ptr -> do+  size <- act (realToFrac val) ptr+  when (size == -1) .+    fail $ "Data.Double.Conversion.ByteString." ++ func +++           ": conversion failed (invalid precision requested)"+  return (ptr `plusPtr` (fromIntegral size))
+ Data/Double/Conversion/Internal/FFI.hs view
@@ -0,0 +1,125 @@+{-# LANGUAGE CPP, ForeignFunctionInterface, MagicHash, TypeFamilies,+             UnliftedFFITypes #-}++-- |+-- Module      : Data.Double.Conversion.FFI+-- Copyright   : (c) 2011 MailRank, Inc.+--+-- License     : BSD-style+-- Maintainer  : bos@serpentine.com+-- Stability   : experimental+-- Portability : GHC+--+-- FFI interface support for converting between+-- floating point values and text.++module Data.Double.Conversion.Internal.FFI+    (+      ForeignFloating+    , c_Text_ToExponential+    , c_Text_ToExponentialFloat+    , c_Text_ToFixed+    , c_Text_ToFixedFloat+    , c_Text_ToPrecision+    , c_Text_ToPrecisionFloat+    , c_Text_ToShortest+    , c_Text_ToShortestFloat+    , c_ToExponentialLength+    , c_ToFixedLength+    , c_ToPrecisionLength+    , c_ToShortestLength+    , c_ToExponential+    , c_ToExponentialFloat+    , c_ToFixed+    , c_ToFixedFloat+    , c_ToPrecision+    , c_ToPrecisionFloat+    , c_ToShortest+    , c_ToShortestFloat+    ) where++import Data.Word (Word8)+#if __GLASGOW_HASKELL__ >= 703+import Foreign.C.Types (CDouble(CDouble), CFloat(CFloat), CInt(CInt))+#else+import Foreign.C.Types (CDouble, CFloat, CInt)+#endif+import Foreign.Ptr (Ptr)+import GHC.Prim (MutableByteArray#)++type family ForeignFloating h :: *++type instance ForeignFloating Double = CDouble+type instance ForeignFloating Float = CFloat++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 -> Ptr Word8 -> IO CInt++foreign import ccall unsafe "hs-double-conversion.h _hs_ToShortestFloat"+    c_ToShortestFloat :: CFloat -> Ptr Word8 -> 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 -> Ptr Word8 -> CInt -> IO CInt++foreign import ccall unsafe "hs-double-conversion.h _hs_ToFixedFloat"+    c_ToFixedFloat :: CFloat -> Ptr Word8 -> 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 -> Ptr Word8 -> CInt -> IO CInt++foreign import ccall unsafe "hs-double-conversion.h _hs_ToExponentialFloat"+    c_ToExponentialFloat :: CFloat -> Ptr Word8 -> 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 -> Ptr Word8 -> CInt -> IO CInt++foreign import ccall unsafe "hs-double-conversion.h _hs_ToPrecisionFloat"+    c_ToPrecisionFloat :: CFloat -> Ptr Word8 -> CInt -> IO CInt++#if MIN_VERSION_text(2,0,0)+foreign import ccall unsafe "hs-double-conversion.h _hs_ToShortest"+    c_Text_ToShortest :: CDouble -> MutableByteArray# s -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_ToShortestFloat"+    c_Text_ToShortestFloat :: CFloat -> MutableByteArray# s -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_ToFixed"+    c_Text_ToFixed :: CDouble -> MutableByteArray# s -> CInt -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_ToFixedFloat"+    c_Text_ToFixedFloat :: CFloat -> MutableByteArray# s-> CInt -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_ToExponential"+    c_Text_ToExponential :: CDouble -> MutableByteArray# s -> CInt -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_ToExponentialFloat"+    c_Text_ToExponentialFloat :: CFloat -> MutableByteArray# s -> CInt -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_ToPrecision"+    c_Text_ToPrecision :: CDouble -> MutableByteArray# s -> CInt -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_ToPrecisionFloat"+    c_Text_ToPrecisionFloat :: CFloat -> MutableByteArray# s -> CInt -> IO CInt+#else+foreign import ccall unsafe "hs-double-conversion.h _hs_Text_ToShortest"+    c_Text_ToShortest :: CDouble -> MutableByteArray# s -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_Text_ToShortestFloat"+    c_Text_ToShortestFloat :: CFloat -> MutableByteArray# s -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_Text_ToFixed"+    c_Text_ToFixed :: CDouble -> MutableByteArray# s -> CInt -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_Text_ToFixedFloat"+    c_Text_ToFixedFloat :: CFloat -> MutableByteArray# s -> CInt -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_Text_ToExponential"+    c_Text_ToExponential :: CDouble -> MutableByteArray# s -> CInt -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_Text_ToExponentialFloat"+    c_Text_ToExponentialFloat :: CFloat -> MutableByteArray# s -> CInt -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_Text_ToPrecision"+    c_Text_ToPrecision :: CDouble -> MutableByteArray# s -> CInt -> IO CInt+foreign import ccall unsafe "hs-double-conversion.h _hs_Text_ToPrecisionFloat"+    c_Text_ToPrecisionFloat :: CFloat -> MutableByteArray# s -> CInt -> IO CInt+#endif
+ Data/Double/Conversion/Internal/Text.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE CPP, MagicHash, Rank2Types, TypeFamilies, BangPatterns, TypeOperators #-}++-- |+-- Module      : Data.Double.Conversion.Text+-- Copyright   : (c) 2011 MailRank, Inc.+--+-- License     : BSD-style+-- Maintainer  : bos@serpentine.com+-- Stability   : experimental+-- Portability : GHC+--+-- Fast, efficient support for converting between double precision+-- floating point values and text.+--+-- These functions are about 30 times faster than the default 'show'+-- implementation for the 'Double' type.++module Data.Double.Conversion.Internal.Text+    (+      convert+    ) 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 (ST, runST)+import Data.Double.Conversion.Internal.FFI (ForeignFloating)+import qualified Data.Text.Array as A+import Data.Text.Internal (Text(Text))+import Foreign.C.Types (CDouble, CFloat, CInt)+import GHC.Prim (MutableByteArray#)+++convert :: (RealFloat a, RealFloat b, b ~ ForeignFloating a) => String -> CInt+        -> (forall s. b -> MutableByteArray# s -> IO CInt)+        -> a -> Text+{-# SPECIALIZE convert :: String -> CInt -> (forall s. CDouble -> MutableByteArray# s -> IO CInt) -> Double -> Text #-}+{-# SPECIALIZE convert :: String -> CInt -> (forall s. CFloat -> MutableByteArray# s -> IO CInt) -> Float -> Text #-}+{-# INLINABLE convert #-}+convert func len act val = runST go+  where+    go :: (forall s. ST s Text)+    go = do+      buf <- A.new (fromIntegral len)+#if MIN_VERSION_text(2,0,0)+      let !(A.MutableByteArray ma) = buf+#else+      let ma = A.maBA buf+#endif+      size <- unsafeIOToST $ act (realToFrac val) ma+      when (size == -1) .+        error $ "Data.Double.Conversion.Text." ++ func +++               ": conversion failed (invalid precision requested)"+      frozen <- A.unsafeFreeze buf+      return $ Text frozen 0 (fromIntegral size)
+ Data/Double/Conversion/Internal/TextBuilder.hs view
@@ -0,0 +1,54 @@+{-# LANGUAGE CPP, MagicHash, Rank2Types, TypeFamilies, TypeOperators #-}+-- |+-- Module      : Data.Double.Conversion.TextBuilder+-- Copyright   : (c) 2011 MailRank, Inc.+--+-- License     : BSD-style+-- Maintainer  : bos@serpentine.com+-- Stability   : experimental+-- Portability : GHC+--+-- Fast, efficient support for converting between double precision+-- floating point values and text.+--++module Data.Double.Conversion.Internal.TextBuilder+    (+      convert+    ) 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 Data.Double.Conversion.Internal.FFI (ForeignFloating)+import qualified Data.Text.Array as A+import Data.Text.Internal.Builder (Builder, writeN)+import Foreign.C.Types (CDouble, CFloat, CInt)+import GHC.Prim (MutableByteArray#)+import Control.Monad.ST (runST)++convert :: (RealFloat a, RealFloat b, b ~ ForeignFloating a) => String -> CInt+        -> (forall s. b -> MutableByteArray# s -> IO CInt)+        -> a -> Builder+{-# SPECIALIZE convert :: String -> CInt -> (forall s. CDouble -> MutableByteArray# s -> IO CInt) -> Double -> Builder #-}+{-# SPECIALIZE convert :: String -> CInt -> (forall s. CFloat -> MutableByteArray# s -> IO CInt) -> Float -> Builder #-}+{-# INLINABLE convert #-}+convert func len act val = runST $ do +#if MIN_VERSION_text(2,0,0)+  mTempArr@(A.MutableByteArray tempMArr) <- A.new (fromIntegral len)+#else+  mTempArr@(A.MArray tempMArr) <- A.new (fromIntegral len)+#endif+  size <- unsafeIOToST $ act (realToFrac val) tempMArr+  tempArr <- A.unsafeFreeze mTempArr+  when (size == -1) .+      error $ "Data.Double.Conversion.Text." ++ func +++              ": conversion failed."+#if MIN_VERSION_text(2,0,0)+  return $ writeN (fromIntegral size) $ \mArr _ -> A.copyI (fromIntegral size) mArr 0 tempArr 0+#else+  return $ writeN (fromIntegral size) $ \mArr _ -> A.copyI mArr 0 tempArr 0 (fromIntegral size)+#endif
Data/Double/Conversion/Text.hs view
@@ -9,6 +9,13 @@ -- Stability   : experimental -- Portability : GHC --+-- This module left now only for compatibility and should not be used+-- in new projects. +-- Please, use Convertable type class from Data.Double.Conversion.Convertable+--+-- It is espesially recommended to convert a large amount of numbers via text builder+-- using methods of Convertable type class. It is about 10-15x faster.+--  -- Fast, efficient support for converting between double precision -- floating point values and text. --@@ -23,62 +30,27 @@     , 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+import qualified Data.Double.Conversion.Convertable+import Data.Text.Internal (Text)  -- | Compute a representation in exponential format with the requested -- number of digits after the decimal point. The last emitted digit is -- rounded.  If -1 digits are requested, then the shortest exponential -- representation is computed. toExponential :: Int -> Double -> Text-toExponential ndigits = convert "toExponential" len $ \val mba ->-                        c_Text_ToExponential val mba (fromIntegral ndigits)-  where len = c_ToExponentialLength-        {-# NOINLINE len #-}+toExponential = Data.Double.Conversion.Convertable.toExponential  -- | Compute a decimal representation with a fixed number of digits -- after the decimal point. The last emitted digit is rounded. toFixed :: Int -> Double -> Text-toFixed ndigits = convert "toFixed" len $ \val mba ->-                  c_Text_ToFixed val mba (fromIntegral ndigits)-  where len = c_ToFixedLength-        {-# NOINLINE len #-}+toFixed = Data.Double.Conversion.Convertable.toFixed  -- | Compute the shortest string of digits that correctly represent -- the input number. toShortest :: Double -> Text-toShortest = convert "toShortest" len c_Text_ToShortest-  where len = c_ToShortestLength-        {-# NOINLINE len #-}+toShortest = Data.Double.Conversion.Convertable.toShortest  -- | Compute @precision@ leading digits of the given value either in -- exponential or decimal format. The last computed digit is rounded. toPrecision :: Int -> Double -> Text-toPrecision ndigits = convert "toPrecision" len $ \val mba ->-                      c_Text_ToPrecision val mba (fromIntegral ndigits)-  where len = c_ToPrecisionLength-        {-# NOINLINE len #-}--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)+toPrecision = Data.Double.Conversion.Convertable.toPrecision
README.markdown view
@@ -3,7 +3,7 @@ double-conversion is a fast Haskell library for converting between double precision floating point numbers and text strings.  It is implemented as a binding to the V8-derived C++ [double-conversion-library](https://github.com/floitsch/double-conversion).+library](https://github.com/google/double-conversion).  # Join in! @@ -11,17 +11,11 @@ and other improvements.  Please report bugs via the-[github issue tracker](https://github.com/bos/double-conversion/issues).--Master [git repository](https://github.com/bos/double-conversion):--* `git clone git://github.com/bos/double-conversion.git`--There's also a [Mercurial mirror](https://bitbucket.org/bos/double-conversion):+[github issue tracker](https://github.com/haskell/double-conversion/issues). -* `hg clone https://bitbucket.org/bos/double-conversion`+Master [git repository](https://github.com/haskell/double-conversion): -(You can create and contribute changes using either git or Mercurial.)+* `git clone git://github.com/haskell/double-conversion`  Authors -------
benchmarks/Benchmarks.hs view
@@ -1,28 +1,120 @@ {-# LANGUAGE ForeignFunctionInterface, OverloadedStrings #-}  import Criterion.Main-import qualified Data.Double.Conversion.ByteString as B-import qualified Data.Double.Conversion.Text as T-import Foreign.C.Types (CInt(CInt), CDouble(CDouble))+import qualified Data.ByteString as BSS+import qualified Data.ByteString.Builder as BB+import qualified Data.ByteString.Builder.Extra as BBE+import qualified Data.ByteString.Lazy as BSL+import qualified Data.Double.Conversion.Convertable as BL+import Data.List (foldr)+import Data.Monoid ((<>)) import qualified Data.Text as T+import qualified Data.Text.Internal.Builder as BT+import qualified Data.Text.Lazy as TL+import Foreign.C.Types (CDouble(CDouble), CInt(CInt)) import qualified Text.Show.ByteString as BS +testList = [2.08345919 .. 20002.08345919] :: [Double]+testFloatList = [2.08345919 .. 20002.08345919] :: [Float]++testListBSBuilder :: (Double -> BB.Builder) -> [Double] -> BSS.ByteString+testListBSBuilder func list = BSL.toStrict $ BBE.toLazyByteStringWith (BBE.safeStrategy 128 128) BSL.empty $ foldr (\x y -> (func x <> ", ") <> y) mempty list++testListBSBuilderFloat :: (Float -> BB.Builder) -> [Float] -> BSS.ByteString+testListBSBuilderFloat func list = BSL.toStrict $ BBE.toLazyByteStringWith (BBE.safeStrategy 128 128) BSL.empty $ foldr (\x y -> (func x <> ", ") <> y) mempty list++testListByteString :: (Double -> BSS.ByteString) -> [Double] -> BSS.ByteString+testListByteString func = foldr (\x y -> (func x <> ", ") <> y) mempty++testListByteStringFloat :: (Float -> BSS.ByteString) -> [Float] -> BSS.ByteString+testListByteStringFloat func = foldr (\x y -> (func x <> ", ") <> y) mempty++testListText :: (Double -> T.Text) -> [Double] -> T.Text+testListText func = foldr (\x y -> (func x <> ", ") <> y) mempty++testListTextFloat :: (Float -> T.Text) -> [Float] -> T.Text+testListTextFloat func = foldr (\x y -> (func x <> ", ") <> y) mempty++testListTextBuilder :: (Double -> BT.Builder) -> [Double] -> T.Text+testListTextBuilder func list = TL.toStrict $ BT.toLazyText $ foldr (\x y -> (func x <> ", ") <> y) mempty list++testListTextBuilderFloat :: (Float -> BT.Builder) -> [Float] -> T.Text+testListTextBuilderFloat func list = TL.toStrict $ BT.toLazyText $ foldr (\x y -> (func x <> ", ") <> y) mempty list++testFuncBuilderDefault :: [Double] -> BSS.ByteString+testFuncBuilderDefault = \list -> BSL.toStrict $ BB.toLazyByteString $ foldr (\x y -> (BB.doubleDec x <> ", ") <> y) mempty list++testFuncBuilderDefaultFloat :: [Float] -> BSS.ByteString+testFuncBuilderDefaultFloat = \list -> BSL.toStrict $ BB.toLazyByteString $ foldr (\x y -> (BB.floatDec x <> ", ") <> y) mempty list++ main = defaultMain [-         bgroup "haskell" [+         bgroup "haskell-single" [            bench "show" $ nf show (pi::Double)          , bench "bytestring-show" $ whnf BS.show (pi::Double)          , bgroup "text" [-             bench "toShortest" $ whnf T.toShortest pi-           , bench "toExponential" $ whnf (T.toExponential 3) pi-           , bench "toPrecision" $ whnf (T.toExponential 8) pi-           , bench "toFixed" $ whnf (T.toFixed 8) pi+             bench "toShortest" $ whnf (BL.toShortest :: Double -> T.Text) pi+           , bench "toExponential" $ whnf ((BL.toExponential 3) :: Double -> T.Text) pi+           , bench "toPrecision" $ whnf ((BL.toExponential 8) :: Double -> T.Text) pi+           , bench "toFixed" $ whnf ((BL.toFixed 8) :: Double -> T.Text) pi            ]          , bgroup "bytestring" [-             bench "toShortest" $ whnf B.toShortest pi-           , bench "toExponential" $ whnf (B.toExponential 3) pi-           , bench "toPrecision" $ whnf (B.toExponential 8) pi-           , bench "toFixed" $ whnf (B.toFixed 8) pi+             bench "toShortest" $ whnf (BL.toShortest :: Double -> BSS.ByteString) pi+           , bench "toExponential" $ whnf ((BL.toExponential 3) :: Double -> BSS.ByteString) pi+           , bench "toPrecision" $ whnf ((BL.toExponential 8) :: Double -> BSS.ByteString) pi+           , bench "toFixed" $ whnf ((BL.toFixed 8) :: Double -> BSS.ByteString) pi            ]+         , bgroup "bytestringBuilder" [+             bench "toShortest" $ nf (BB.toLazyByteString . BL.toShortest) (pi::Double)+           , bench "toPrecision" $ nf (BB.toLazyByteString . (BL.toExponential 8)) (pi::Double)+           , bench "toPrecision" $ nf (BB.toLazyByteString . (BL.toPrecision 8)) (pi::Double)+           , bench "toFixed" $ nf (BB.toLazyByteString . (BL.toFixed 8)) (pi::Double)+           ]+         ]+       , bgroup "Haskell-list" [+           bgroup "bytestring" [+             bench "toShortest" $ nf (testListByteString BL.toShortest) testList+           , bench "toExponential" $ nf (testListByteString $ BL.toExponential 8) testList+           , bench "toPrecision" $ nf (testListByteString $ BL.toPrecision 8) testList+           , bench "toFixed" $ nf (testListByteString $ BL.toFixed 8) testList]+       , bgroup "bytestring-float" [+             bench "toShortest" $ nf (testListByteStringFloat BL.toShortest) testFloatList+           , bench "toExponential" $ nf (testListByteStringFloat $ BL.toExponential 8) testFloatList+           , bench "toPrecision" $ nf (testListByteStringFloat $ BL.toPrecision 8) testFloatList+           , bench "toFixed" $ nf (testListByteStringFloat $ BL.toFixed 8) testFloatList]+        ,  bgroup "bytestring-builder" [+             bench "toShortest" $ nf (testListBSBuilder BL.toShortest) testList+           , bench "toExponential" $ nf (testListBSBuilder $ BL.toExponential 8) testList+           , bench "toPrecision" $ nf (testListBSBuilder $ BL.toPrecision 8) testList+           , bench "toFixed" $ nf (testListBSBuilder $ BL.toFixed 8) testList ]+        ,  bgroup "bytestring-builder-float" [+             bench "toShortest" $ nf (testListBSBuilderFloat BL.toShortest) testFloatList+           , bench "toExponential" $ nf (testListBSBuilderFloat $ BL.toExponential 8) testFloatList+           , bench "toPrecision" $ nf (testListBSBuilderFloat $ BL.toPrecision 8) testFloatList+           , bench "toFixed" $ nf (testListBSBuilderFloat $ BL.toFixed 8) testFloatList ]+        ,  bgroup "text" [+             bench "toShortest" $ nf (testListText BL.toShortest) testList+           , bench "toExponential" $ nf (testListText $ BL.toExponential 8) testList+           , bench "toPrecision" $ nf (testListText $ BL.toPrecision 8) testList+           , bench "toFixed" $ nf (testListText $ BL.toFixed 8) testList ]+        ,  bgroup "text-float" [+             bench "toShortest" $ nf (testListTextFloat BL.toShortest) testFloatList+           , bench "toExponential" $ nf (testListTextFloat $ BL.toExponential 8) testFloatList+           , bench "toPrecision" $ nf (testListTextFloat $ BL.toPrecision 8) testFloatList+           , bench "toFixed" $ nf (testListTextFloat $ BL.toFixed 8) testFloatList ]+        ,  bgroup "text-builder" [+             bench "toShortest" $ nf (testListTextBuilder BL.toShortest) testList+           , bench "toExponential" $ nf (testListTextBuilder $ BL.toExponential 8) testList+           , bench "toPrecision" $ nf (testListTextBuilder$ BL.toPrecision 8) testList+           , bench "toFixed" $ nf (testListTextBuilder $ BL.toFixed 8) testList ]+        ,  bgroup "text-builder-float" [+             bench "toShortest" $ nf (testListTextBuilderFloat BL.toShortest) testFloatList+           , bench "toExponential" $ nf (testListTextBuilderFloat $ BL.toExponential 8) testFloatList+           , bench "toPrecision" $ nf (testListTextBuilderFloat $ BL.toPrecision 8) testFloatList+           , bench "toFixed" $ nf (testListTextBuilderFloat $ BL.toFixed 8) testFloatList ]+        ,  bgroup "bytestring-builder-default" [+             bench "Double" $ nf (testFuncBuilderDefault) testList+        ,    bench "Float" $ nf (testFuncBuilderDefaultFloat) testFloatList ]          ]        , bgroup "sprintf" [            bench "exact" $ whnf sprintf_exact pi
benchmarks/double-conversion-benchmarks.cabal view
@@ -10,6 +10,7 @@    build-depends:     base,+    bytestring,      bytestring-show,     criterion >= 0.5.0.10,     double-conversion,
+ cbits/hs-double-conversion-embed.cc view
@@ -0,0 +1,199 @@+#include "double-conversion.h"+#include "hs-double-conversion.h"+#include <stdio.h>++using namespace double_conversion;++static const int kToShortestLength = 26;++extern "C"+int _hs_ToShortestLength(void)+{+  return kToShortestLength;+}++static const int kToFixedLength =+  1 + DoubleToStringConverter::kMaxFixedDigitsBeforePoint ++  1 + DoubleToStringConverter::kMaxFixedDigitsAfterPoint;++extern "C"+int _hs_ToFixedLength(void)+{+  return kToFixedLength;+}++static const int kToExponentialLength =+  DoubleToStringConverter::kMaxExponentialDigits + 8;++extern "C"+int _hs_ToExponentialLength(void)+{+  return kToExponentialLength;+}++static const int kToPrecisionLength =+  DoubleToStringConverter::kMaxPrecisionDigits + 7;++extern "C"+int _hs_ToPrecisionLength(void)+{+  return kToPrecisionLength;+}++static int copy(uint16_t *buf, const StringBuilder& builder, const char *cbuf)+{+  const int pos = builder.position();+  for (int i = 0; i < pos; i++)+    buf[i] = cbuf[i];+  return pos;+}++static int copy(uint16_t *buf, const char *cbuf, const int len)+{+  for (int i = 0; i < len; i++)+    buf[i] = cbuf[i];+  return len;+}++static inline const DoubleToStringConverter& defaultConverter(void)+{+  const int flags = DoubleToStringConverter::UNIQUE_ZERO;+  static DoubleToStringConverter converter(flags,+                                           "Infinity",+                                           "NaN",+                                           'e',+                                           -6, 21,+                                           6, 0);+  return converter;+}++static inline const DoubleToStringConverter& floatConverter(void)+{+  const int flags = DoubleToStringConverter::UNIQUE_ZERO;+  static DoubleToStringConverter converter(flags,+                                           "Infinity",+                                           "NaN",+                                           'e',+                                           -6, 6,+                                           6, 0);+  return converter;+}++extern "C"+int _hs_ToShortest(double value, char *buf)+{+  StringBuilder builder(buf, kToShortestLength);+  return defaultConverter().ToShortest(value, &builder)+    ? builder.position() : -1;+}++extern "C"+int _hs_ToShortestFloat(float value, char *buf)+{+  StringBuilder builder(buf, kToShortestLength);+  return floatConverter().ToShortestSingle(value, &builder)+    ? builder.position() : -1;+}++extern "C"+int _hs_Text_ToShortest(double value, uint16_t *buf)+{+  char cbuf[kToShortestLength];+  return copy(buf, cbuf, _hs_ToShortest(value, cbuf));+}++extern "C"+int _hs_Text_ToShortestFloat(float value, uint16_t *buf)+{+  char cbuf[kToShortestLength];+  return copy(buf, cbuf, _hs_ToShortestFloat(value, cbuf));+}++extern "C"+int _hs_ToFixed(double value, char *buf, const int ndigits)+{+  StringBuilder builder(buf, kToFixedLength);+  return defaultConverter().ToFixed(value, ndigits, &builder)+    ? builder.position() : -1;+}++int _hs_ToFixedFloat(float value, char *buf, const int ndigits)+{+  StringBuilder builder(buf, kToFixedLength);+  return floatConverter().ToFixed(value, ndigits, &builder)+    ? builder.position() : -1;+}++extern "C"+int _hs_Text_ToFixed(double value, uint16_t *buf, const int ndigits)+{+  char cbuf[kToFixedLength];+  return copy(buf, cbuf, _hs_ToFixed(value, cbuf, ndigits));+}++extern "C"+int _hs_Text_ToFixedFloat(float value, uint16_t *buf, const int ndigits)+{+  char cbuf[kToFixedLength];+  return copy(buf, cbuf, _hs_ToFixedFloat(value, cbuf, ndigits));+}++extern "C"+int _hs_ToExponential(double value, char *buf, const int ndigits)+{+  StringBuilder builder(buf, kToExponentialLength);+  return defaultConverter().ToExponential(value, ndigits, &builder)+    ? builder.position() : -1;+}++extern "C"+int _hs_ToExponentialFloat(float value, char *buf, const int ndigits)+{+  StringBuilder builder(buf, kToExponentialLength);+  return floatConverter().ToExponential(value, ndigits, &builder)+    ? builder.position() : -1;+}++extern "C"+int _hs_Text_ToExponential(double value, uint16_t *buf, const int ndigits)+{+  char cbuf[kToExponentialLength];+  return copy(buf, cbuf, _hs_ToExponential(value, cbuf, ndigits));+}++extern "C"+int _hs_Text_ToExponentialFloat(float value, uint16_t *buf, const int ndigits)+{+  char cbuf[kToExponentialLength];+  return copy(buf, cbuf, _hs_ToExponentialFloat(value, cbuf, ndigits));+}++extern "C"+int _hs_ToPrecision(double value, char *buf, const int precision)+{+  StringBuilder builder(buf, kToPrecisionLength);+  return defaultConverter().ToPrecision(value, precision, &builder)+    ? builder.position() : -1;+}++extern "C"+int _hs_ToPrecisionFloat(float value, char *buf, const int precision)+{+  StringBuilder builder(buf, kToPrecisionLength);+  return floatConverter().ToPrecision(value, precision, &builder)+    ? builder.position() : -1;+}++extern "C"+int _hs_Text_ToPrecision(double value, uint16_t *buf, const int precision)+{+  char cbuf[kToPrecisionLength];+  return copy(buf, cbuf, _hs_ToPrecision(value, cbuf, precision));+}++extern "C"+int _hs_Text_ToPrecisionFloat(float value, uint16_t *buf, const int precision)+{+  char cbuf[kToPrecisionLength];+  return copy(buf, cbuf, _hs_ToPrecisionFloat(value, cbuf, precision));+}
cbits/hs-double-conversion.cc view
@@ -1,4 +1,4 @@-#include "double-conversion.h"+#include "double-conversion/double-conversion.h" #include "hs-double-conversion.h" #include <stdio.h> @@ -67,6 +67,18 @@   return converter; } +static inline const DoubleToStringConverter& floatConverter(void)+{+  const int flags = DoubleToStringConverter::UNIQUE_ZERO;+  static DoubleToStringConverter converter(flags,+                                           "Infinity",+                                           "NaN",+                                           'e',+                                           -6, 6,+                                           6, 0);+  return converter;+}+ extern "C" int _hs_ToShortest(double value, char *buf) {@@ -76,6 +88,14 @@ }  extern "C"+int _hs_ToShortestFloat(float value, char *buf)+{+  StringBuilder builder(buf, kToShortestLength);+  return floatConverter().ToShortestSingle(value, &builder)+    ? builder.position() : -1;+}++extern "C" int _hs_Text_ToShortest(double value, uint16_t *buf) {   char cbuf[kToShortestLength];@@ -83,6 +103,13 @@ }  extern "C"+int _hs_Text_ToShortestFloat(float value, uint16_t *buf)+{+  char cbuf[kToShortestLength];+  return copy(buf, cbuf, _hs_ToShortestFloat(value, cbuf));+}++extern "C" int _hs_ToFixed(double value, char *buf, const int ndigits) {   StringBuilder builder(buf, kToFixedLength);@@ -90,6 +117,13 @@     ? builder.position() : -1; } +int _hs_ToFixedFloat(float value, char *buf, const int ndigits)+{+  StringBuilder builder(buf, kToFixedLength);+  return floatConverter().ToFixed(value, ndigits, &builder)+    ? builder.position() : -1;+}+ extern "C" int _hs_Text_ToFixed(double value, uint16_t *buf, const int ndigits) {@@ -98,6 +132,13 @@ }  extern "C"+int _hs_Text_ToFixedFloat(float value, uint16_t *buf, const int ndigits)+{+  char cbuf[kToFixedLength];+  return copy(buf, cbuf, _hs_ToFixedFloat(value, cbuf, ndigits));+}++extern "C" int _hs_ToExponential(double value, char *buf, const int ndigits) {   StringBuilder builder(buf, kToExponentialLength);@@ -106,6 +147,14 @@ }  extern "C"+int _hs_ToExponentialFloat(float value, char *buf, const int ndigits)+{+  StringBuilder builder(buf, kToExponentialLength);+  return floatConverter().ToExponential(value, ndigits, &builder)+    ? builder.position() : -1;+}++extern "C" int _hs_Text_ToExponential(double value, uint16_t *buf, const int ndigits) {   char cbuf[kToExponentialLength];@@ -113,6 +162,13 @@ }  extern "C"+int _hs_Text_ToExponentialFloat(float value, uint16_t *buf, const int ndigits)+{+  char cbuf[kToExponentialLength];+  return copy(buf, cbuf, _hs_ToExponentialFloat(value, cbuf, ndigits));+}++extern "C" int _hs_ToPrecision(double value, char *buf, const int precision) {   StringBuilder builder(buf, kToPrecisionLength);@@ -121,8 +177,23 @@ }  extern "C"+int _hs_ToPrecisionFloat(float value, char *buf, const int precision)+{+  StringBuilder builder(buf, kToPrecisionLength);+  return floatConverter().ToPrecision(value, precision, &builder)+    ? builder.position() : -1;+}++extern "C" int _hs_Text_ToPrecision(double value, uint16_t *buf, const int precision) {   char cbuf[kToPrecisionLength];   return copy(buf, cbuf, _hs_ToPrecision(value, cbuf, precision));+}++extern "C"+int _hs_Text_ToPrecisionFloat(float value, uint16_t *buf, const int precision)+{+  char cbuf[kToPrecisionLength];+  return copy(buf, cbuf, _hs_ToPrecisionFloat(value, cbuf, precision)); }
double-conversion.cabal view
@@ -1,31 +1,37 @@+cabal-version:  2.2 name:           double-conversion-version:        2.0.2.0-license:        BSD3+version:        2.0.5.0+license:        BSD-2-Clause license-file:   LICENSE-homepage:       https://github.com/bos/double-conversion-bug-reports:    https://github.com/bos/double-conversion/issues+homepage:       https://github.com/haskell/double-conversion+bug-reports:    https://github.com/haskell/double-conversion/issues category:       Text author:         Bryan O'Sullivan <bos@serpentine.com> maintainer:     Bryan O'Sullivan <bos@serpentine.com> stability:      experimental-synopsis:       Fast conversion between double precision floating point and text-cabal-version:  >= 1.8+synopsis:       Fast conversion between single and double precision floating point and text build-type:     Simple+tested-with:    GHC ==9.0.2 || ==9.2.8 || ==9.4.7 || ==9.6.2 description:-    A library that performs fast, accurate conversion between double-    precision floating point and text.+    A library that performs fast, accurate conversion between +    floating point and text.     .     This library is implemented as bindings to the C++     @double-conversion@ library written by Florian Loitsch at Google:     <https://github.com/floitsch/double-conversion>.     .+    Now it can convert single precision numbers, and also it can create +    Builder, instead of bytestring or text. +    .     The 'Text' versions of these functions are about 30 times faster     than the default 'show' implementation for the 'Double' type.     .-    The 'ByteString' versions are /slower/ than the 'Text' versions;-    roughly half the speed.  (This seems to be due to the cost of-    allocating 'ByteString' values via @malloc@.)+    The 'ByteString' versions are have very close speed to the 'Text' versions;     .+    Builder versions (both for Text and Bytestring) are slower on single value,+    but they are much faster on large number of values +    (up to 20x faster on list with 20000 doubles).+    .     As a final note, be aware that the @bytestring-show@ package is     about 50% slower than simply using 'show'. @@ -59,39 +65,60 @@   default: False   manual: True +flag embedded_double_conversion+  description: embed the C++ double_conversion library+  default: True+ library-  c-sources:-    cbits/hs-double-conversion.cc-    double-conversion/src/bignum.cc-    double-conversion/src/bignum-dtoa.cc-    double-conversion/src/cached-powers.cc-    double-conversion/src/diy-fp.cc-    double-conversion/src/double-conversion.cc-    double-conversion/src/fast-dtoa.cc-    double-conversion/src/fixed-dtoa.cc-    double-conversion/src/strtod.cc+  if impl(ghc >= 9.4)+    build-depends: system-cxx-std-lib == 1.0 -  if os(windows)-    if arch(x86_64)+  elif os(darwin) || os(freebsd)+    extra-libraries: c+++  elif os(windows)+    if arch(x86_64) && impl(ghc < 8.6.5)       extra-libraries: stdc++-6 gcc_s_seh-1-    else+    elif arch(x86_64)+      extra-libraries: stdc++ gcc_s_seh-1+    elif impl(ghc >= 8.6.5)+      extra-libraries: stdc++ gcc_s_dw2-1+    else        extra-libraries: stdc++-6 gcc_s_dw2-1   else-    if os(darwin)-      extra-libraries: c++-    else-      extra-libraries: stdc+++    extra-libraries: stdc++ +  if flag(embedded_double_conversion)+    cxx-sources:+      cbits/hs-double-conversion-embed.cc++      double-conversion/src/bignum.cc+      double-conversion/src/bignum-dtoa.cc+      double-conversion/src/cached-powers.cc+      double-conversion/src/diy-fp.cc+      double-conversion/src/double-conversion.cc+      double-conversion/src/fast-dtoa.cc+      double-conversion/src/fixed-dtoa.cc+      double-conversion/src/strtod.cc+    include-dirs: double-conversion/src+  else+    extra-libraries: double-conversion+    cxx-sources:+      cbits/hs-double-conversion.cc+   include-dirs:-    double-conversion/src     include    exposed-modules:+    Data.Double.Conversion.Convertable     Data.Double.Conversion.ByteString     Data.Double.Conversion.Text    other-modules:-    Data.Double.Conversion.FFI+    Data.Double.Conversion.Internal.FFI+    Data.Double.Conversion.Internal.ByteString+    Data.Double.Conversion.Internal.ByteStringBuilder+    Data.Double.Conversion.Internal.Text+    Data.Double.Conversion.Internal.TextBuilder    build-depends:     base == 4.*,@@ -100,13 +127,15 @@     text >= 0.11.0.8    if flag(developer)-    ghc-options: -Werror+    ghc-options: -Werror      ghc-prof-options: -auto-all   else-    cc-options: -DNDEBUG+    cc-options: -DNDEBUG  -  ghc-options: -Wall+  ghc-options: -Wall  +  default-language: Haskell2010+ test-suite tests   type: exitcode-stdio-1.0   hs-source-dirs: tests@@ -122,11 +151,8 @@     test-framework-hunit,     test-framework-quickcheck2,     text+  default-language: Haskell2010  source-repository head   type:     git-  location: https://github.com/bos/double-conversion--source-repository head-  type:     mercurial-  location: https://bitbucket.org/bos/double-conversion+  location: https://github.com/haskell/double-conversion
double-conversion/CMakeLists.txt view
@@ -1,44 +1,34 @@-cmake_minimum_required(VERSION 2.8)-project(double-conversion)--# pick a version #-set(double-conversion_VERSION 2.0.1)-set(double-conversion_SOVERSION_MAJOR 1)-set(double-conversion_SOVERSION_MINOR 0)-set(double-conversion_SOVERSION_PATCH 0)-set(double-conversion_SOVERSION-  ${double-conversion_SOVERSION_MAJOR}.${double-conversion_SOVERSION_MINOR}.${double-conversion_SOVERSION_PATCH})--# set paths for install -- empty initially-# Offer the user the choice of overriding the installation directories-set(INSTALL_BIN_DIR CACHE PATH "Installation directory for libraries")-set(INSTALL_LIB_DIR CACHE PATH "Installation directory for libraries")-set(INSTALL_INCLUDE_DIR CACHE PATH "Installation directory for include")-# set suffix for CMake files used for packaging-if(WIN32 AND NOT CYGWIN)-  set(INSTALL_CMAKE_DIR CMake)-else()-  set(INSTALL_CMAKE_DIR lib/CMake/double-conversion)-endif()+cmake_minimum_required(VERSION 3.0)+project(double-conversion VERSION 3.0.0) -# Make relative paths absolute (needed later)-foreach(p LIB BIN INCLUDE CMAKE)-  set(var INSTALL_${p}_DIR)-  if(NOT IS_ABSOLUTE "${${var}}")-    set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")-  endif()-endforeach()+set(headers+    double-conversion/bignum.h+    double-conversion/cached-powers.h+    double-conversion/diy-fp.h+    double-conversion/double-conversion.h+    double-conversion/fast-dtoa.h+    double-conversion/fixed-dtoa.h+    double-conversion/ieee.h+    double-conversion/strtod.h+    double-conversion/utils.h) -#-# set up include dirs-include_directories("${PROJECT_SOURCE_DIR}/src"-  "${PROJECT_BINARY_DIR}"-  )+add_library(double-conversion+            double-conversion/bignum.cc+            double-conversion/bignum-dtoa.cc+            double-conversion/cached-powers.cc+            double-conversion/diy-fp.cc+            double-conversion/double-conversion.cc+            double-conversion/fast-dtoa.cc+            double-conversion/fixed-dtoa.cc+            double-conversion/strtod.cc+            ${headers})+target_include_directories(+    double-conversion PUBLIC+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>) -# Add src subdirectory-add_subdirectory(src)+# pick a version #+set_property(TARGET double-conversion PROPERTY SOVERSION ${PROJECT_VERSION}) -# # set up testing if requested option(BUILD_TESTING "Build test programs" OFF) if(BUILD_TESTING)@@ -47,47 +37,75 @@   add_subdirectory(test) endif() -#-# mention the library target as export library-export(TARGETS double-conversion-  FILE "${PROJECT_BINARY_DIR}/double-conversionLibraryDepends.cmake")+####+# Installation (https://github.com/forexample/package-example) -#-# set this build as an importable package-export(PACKAGE double-conversion)+# Layout. This works for all platforms:+#   * <prefix>/lib/cmake/<PROJECT-NAME>+#   * <prefix>/lib/+#   * <prefix>/include/+set(config_install_dir "lib/cmake/${PROJECT_NAME}")+set(include_install_dir "include") -#-# make a cmake file -- in this case, all that needs defining-# is double-conversion_INCLUDE_DIRS-configure_file(double-conversionBuildTreeSettings.cmake.in-  "${PROJECT_BINARY_DIR}/double-conversionBuildTreeSettings.cmake"-  @ONLY)+set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated") -#-# determine where include is relative to the CMake dir in-# in installed tree-file(RELATIVE_PATH CONF_REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}"-  "${INSTALL_INCLUDE_DIR}")+# Configuration+set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")+set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")+set(targets_export_name "${PROJECT_NAME}Targets")+set(namespace "${PROJECT_NAME}::") -#-# sets up config to be used by CMake find_package-configure_file(double-conversionConfig.cmake.in-  "${PROJECT_BINARY_DIR}/double-conversionConfig.cmake"-  @ONLY)-#-# Export version # checked by find_package-configure_file(double-conversionConfigVersion.cmake.in-  "${PROJECT_BINARY_DIR}/double-conversionConfigVersion.cmake"-  @ONLY)-#-# install config files for find_package-install(FILES-  "${PROJECT_BINARY_DIR}/double-conversionConfig.cmake"-  "${PROJECT_BINARY_DIR}/double-conversionConfigVersion.cmake"-  DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)+# Include module with function 'write_basic_package_version_file'+include(CMakePackageConfigHelpers) +# Configure '<PROJECT-NAME>ConfigVersion.cmake'+# Note: PROJECT_VERSION is used as a VERSION+write_basic_package_version_file(+    "${version_config}" COMPATIBILITY SameMajorVersion+) -#-# generates install cmake files to find libraries in installation.-install(EXPORT double-conversionLibraryDepends DESTINATION-  "${INSTALL_CMAKE_DIR}" COMPONENT dev)+# Configure '<PROJECT-NAME>Config.cmake'+# Use variables:+#   * targets_export_name+#   * PROJECT_NAME+configure_package_config_file(+    "cmake/Config.cmake.in"+    "${project_config}"+    INSTALL_DESTINATION "${config_install_dir}"+)++# Targets:+#   * <prefix>/lib/libdouble-conversion.a+#   * header location after install: <prefix>/include/double-conversion/*.h+#   * headers can be included by C++ code `#include <double-conversion/*.h>`+install(+    TARGETS double-conversion+    EXPORT "${targets_export_name}"+    LIBRARY DESTINATION "lib"+    ARCHIVE DESTINATION "lib"+    RUNTIME DESTINATION "bin"+    INCLUDES DESTINATION "${include_install_dir}"+)++# Headers:+#   * double-conversion/*.h -> <prefix>/include/double-conversion/*.h+install(+    FILES ${headers}+    DESTINATION "${include_install_dir}/double-conversion"+)++# Config+#   * <prefix>/lib/cmake/double-conversion/double-conversionConfig.cmake+#   * <prefix>/lib/cmake/double-conversion/double-conversionConfigVersion.cmake+install(+    FILES "${project_config}" "${version_config}"+    DESTINATION "${config_install_dir}"+)++# Config+#   * <prefix>/lib/cmake/double-conversion/double-conversionTargets.cmake+install(+    EXPORT "${targets_export_name}"+    NAMESPACE "${namespace}"+    DESTINATION "${config_install_dir}"+)
double-conversion/Changelog view
@@ -1,3 +1,33 @@+2017-12-06:+  Renamed `DISALLOW_COPY_AND_ASSIGN` and `DISALLOW_IMPLICIT_CONSTRUCTORS`+  macros to `DC_DISALLOW_COPY_AND_ASSIGN` and+  `DC_DISALLOW_IMPLICIT_CONSTRUCTORS` to make it easier to integrate the+  library with other libraries that have similar macros.++2017-08-05:+  Tagged v3.0.0.+  Due to the directory rename switching to a new version number.+  The API for the library itself hasn't changed.++2017-03-04:+  Avoid negative shift. Fixes #41.++2016-11-17:+  Support RISC-V.+++2016-09-10:+  Add fPIC flag on x86_64 if the compiler supports it. Fixes #34.++2015 and 2016:+  Lots of improvements to the build system.++2015:+  Warning fixes.++2015-05-19:+  Rename 'src' directory to 'double-conversion'.+ 2014-03-08:   Update version number for cmake.   Support shared libraries with cmake.
double-conversion/SConstruct view
@@ -1,7 +1,7 @@ # vim:ft=python import os -double_conversion_sources = ['src/' + x for x in SConscript('src/SConscript')]+double_conversion_sources = ['double-conversion/' + x for x in SConscript('double-conversion/SConscript')] double_conversion_test_sources = ['test/cctest/' + x for x in SConscript('test/cctest/SConscript')]  DESTDIR = ARGUMENTS.get('DESTDIR', '')@@ -9,7 +9,7 @@ lib = ARGUMENTS.get('libsuffix', 'lib') libdir = os.path.join(DESTDIR + prefix, lib) -env = Environment(CPPPATH='#/src', LIBS=['m', 'stdc++'],+env = Environment(CPPPATH='#', LIBS=['m', 'stdc++'],     CXXFLAGS=ARGUMENTS.get('CXXFLAGS', '')) debug = ARGUMENTS.get('debug', 0) optimize = ARGUMENTS.get('optimize', 0)
double-conversion/test/cctest/cctest.h view
@@ -31,7 +31,7 @@ #include <stdio.h> #include <string.h> -#include "utils.h"+#include "double-conversion/utils.h"  #ifndef TEST #define TEST(Name)                                                       \@@ -75,8 +75,11 @@                                      const char* value_source,                                      const char* value) {   if ((expected == NULL && value != NULL) ||-      (expected != NULL && value == NULL) ||-      (expected != NULL && value != NULL && strcmp(expected, value) != 0)) {+      (expected != NULL && value == NULL)) {+    abort();+  }++  if ((expected != NULL && value != NULL && strcmp(expected, value) != 0)) {     printf("%s:%d:\n CHECK_EQ(%s, %s) failed\n"            "#  Expected: %s\n"            "#  Found:    %s\n",@@ -124,10 +127,10 @@   static int test_count();   static CcTest* last() { return last_; }   CcTest* prev() { return prev_; }-  const char* file() { return file_; }-  const char* name() { return name_; }-  const char* dependency() { return dependency_; }-  bool enabled() { return enabled_; }+  const char* file() const { return file_; }+  const char* name() const { return name_; }+  const char* dependency() const { return dependency_; }+  bool enabled() const { return enabled_; }  private:   TestFunction* callback_;   const char* file_;
double-conversion/test/cctest/gay-fixed.cc view

file too large to diff

double-conversion/test/cctest/gay-precision.cc view

file too large to diff

double-conversion/test/cctest/gay-shortest-single.cc view
@@ -28,7 +28,7 @@ // This file contains 100.000 decimal representations of random singles. They // have been generated using Gay's gdtoa to produce the shortest representation. -#include "utils.h"+#include "double-conversion/utils.h"  #include "gay-shortest-single.h" 
double-conversion/test/cctest/gay-shortest.cc view

file too large to diff

double-conversion/test/cctest/test-bignum-dtoa.cc view
@@ -27,15 +27,15 @@  #include <stdlib.h> -#include "bignum-dtoa.h"+#include "double-conversion/bignum-dtoa.h"  #include "cctest.h" #include "gay-fixed.h" #include "gay-precision.h" #include "gay-shortest.h" #include "gay-shortest-single.h"-#include "ieee.h"-#include "utils.h"+#include "double-conversion/ieee.h"+#include "double-conversion/utils.h"  using namespace double_conversion; 
double-conversion/test/cctest/test-bignum.cc view
@@ -29,9 +29,9 @@ #include <string.h>  -#include "bignum.h"+#include "double-conversion/bignum.h" #include "cctest.h"-#include "utils.h"+#include "double-conversion/utils.h"  using namespace double_conversion; @@ -993,6 +993,7 @@   other.AssignUInt16(2);   other.ShiftLeft(500);   CHECK_EQ(5, bignum.DivideModuloIntBignum(other));+  CHECK(bignum.ToHexString(buffer, kBufferSize));   CHECK_EQ("0", buffer);    bignum.AssignUInt16(11);
double-conversion/test/cctest/test-conversions.cc view
@@ -3,9 +3,9 @@ #include <string.h>  #include "cctest.h"-#include "double-conversion.h"-#include "ieee.h"-#include "utils.h"+#include "double-conversion/double-conversion.h"+#include "double-conversion/ieee.h"+#include "double-conversion/utils.h"  // DoubleToString is already tested in test-dtoa.cc. @@ -1804,6 +1804,18 @@   CHECK_EQ(0, processed);  +  flags = StringToDoubleConverter::ALLOW_TRAILING_JUNK;++  CHECK_EQ(123.0, StrToD("123e", flags, 0.0, &processed, &all_used));+  CHECK_EQ(processed, 3);++  CHECK_EQ(123.0, StrToD("123e-", flags, 0.0, &processed, &all_used));+  CHECK_EQ(processed, 3);++  CHECK_EQ(123.0, StrToD("123e-a", flags, 0.0, &processed, &all_used));+  CHECK_EQ(processed, 3);++   flags = StringToDoubleConverter::ALLOW_LEADING_SPACES |       StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN |       StringToDoubleConverter::ALLOW_TRAILING_SPACES |@@ -3184,10 +3196,10 @@   CHECK(all_used);    CHECK_EQ(123.0, StrToD("123e", flags, 0.0, &processed, &all_used));-  CHECK(all_used);+  CHECK_EQ(processed, 3);    CHECK_EQ(123.0, StrToD("123e-", flags, 0.0, &processed, &all_used));-  CHECK(all_used);+  CHECK_EQ(processed, 3);    {     StringToDoubleConverter converter(flags, 0.0, 1.0, "infinity", "NaN");@@ -4709,4 +4721,47 @@                            Single::NaN(),                            &processed, &all_used));   CHECK(all_used);+}+++TEST(StringToDoubleCaseInsensitiveSpecialValues) {+  int processed = 0;++  int flags = StringToDoubleConverter::ALLOW_CASE_INSENSIBILITY |+    StringToDoubleConverter::ALLOW_LEADING_SPACES |+    StringToDoubleConverter::ALLOW_TRAILING_JUNK |+    StringToDoubleConverter::ALLOW_TRAILING_SPACES;++  // Use 1.0 as junk_string_value.+  StringToDoubleConverter converter(flags, 0.0, 1.0, "infinity", "nan");++  CHECK_EQ(Double::NaN(), converter.StringToDouble("+nan", 4, &processed));+  CHECK_EQ(4, processed);++  CHECK_EQ(Double::NaN(), converter.StringToDouble("-nAN", 4, &processed));+  CHECK_EQ(4, processed);++  CHECK_EQ(Double::NaN(), converter.StringToDouble("nAN", 3, &processed));+  CHECK_EQ(3, processed);++  CHECK_EQ(Double::NaN(), converter.StringToDouble("nANabc", 6, &processed));+  CHECK_EQ(3, processed);++  CHECK_EQ(+Double::Infinity(),+           converter.StringToDouble("+Infinity", 9, &processed));+  CHECK_EQ(9, processed);++  CHECK_EQ(-Double::Infinity(),+           converter.StringToDouble("-INFinity", 9, &processed));+  CHECK_EQ(9, processed);++  CHECK_EQ(Double::Infinity(),+           converter.StringToDouble("infINITY", 8, &processed));+  CHECK_EQ(8, processed);++  CHECK_EQ(1.0, converter.StringToDouble("INF", 3, &processed));+  CHECK_EQ(0, processed);++  CHECK_EQ(1.0, converter.StringToDouble("+inf", 4, &processed));+  CHECK_EQ(0, processed); }
double-conversion/test/cctest/test-diy-fp.cc view
@@ -3,8 +3,8 @@ #include <stdlib.h>  #include "cctest.h"-#include "diy-fp.h"-#include "utils.h"+#include "double-conversion/diy-fp.h"+#include "double-conversion/utils.h"   using namespace double_conversion;
double-conversion/test/cctest/test-dtoa.cc view
@@ -27,14 +27,14 @@  #include <stdlib.h> -#include "double-conversion.h"+#include "double-conversion/double-conversion.h"  #include "cctest.h" #include "gay-fixed.h" #include "gay-precision.h" #include "gay-shortest.h" #include "gay-shortest-single.h"-#include "ieee.h"+#include "double-conversion/ieee.h"   using namespace double_conversion;
double-conversion/test/cctest/test-fast-dtoa.cc view
@@ -3,13 +3,13 @@ #include <stdlib.h>  #include "cctest.h"-#include "diy-fp.h"-#include "fast-dtoa.h"+#include "double-conversion/diy-fp.h"+#include "double-conversion/fast-dtoa.h" #include "gay-precision.h" #include "gay-shortest.h" #include "gay-shortest-single.h"-#include "ieee.h"-#include "utils.h"+#include "double-conversion/ieee.h"+#include "double-conversion/utils.h"  using namespace double_conversion; 
double-conversion/test/cctest/test-fixed-dtoa.cc view
@@ -29,10 +29,10 @@   #include "cctest.h"-#include "fixed-dtoa.h"+#include "double-conversion/fixed-dtoa.h" #include "gay-fixed.h"-#include "ieee.h"-#include "utils.h"+#include "double-conversion/ieee.h"+#include "double-conversion/utils.h"  using namespace double_conversion; @@ -485,6 +485,10 @@                       buffer, &length, &point));   CHECK_EQ("1000000000000000128", buffer.start());   CHECK_EQ(19, point);++  CHECK(FastFixedDtoa(2.10861548515811875e+15, 17, buffer, &length, &point));+  CHECK_EQ("210861548515811875", buffer.start());+  CHECK_EQ(16, point); }  
double-conversion/test/cctest/test-ieee.cc view
@@ -3,10 +3,9 @@ #include <stdlib.h>  #include "cctest.h"-#include "diy-fp.h"-#include "ieee.h"-#include "utils.h"-#include "../../src/ieee.h"+#include "double-conversion/diy-fp.h"+#include "double-conversion/utils.h"+#include "double-conversion/ieee.h"   using namespace double_conversion;
double-conversion/test/cctest/test-strtod.cc view
@@ -2,12 +2,12 @@  #include <stdlib.h> -#include "bignum.h"+#include "double-conversion/bignum.h" #include "cctest.h"-#include "diy-fp.h"-#include "ieee.h"-#include "strtod.h"-#include "utils.h"+#include "double-conversion/diy-fp.h"+#include "double-conversion/ieee.h"+#include "double-conversion/strtod.h"+#include "double-conversion/utils.h"  using namespace double_conversion; 
include/hs-double-conversion.h view
@@ -10,16 +10,24 @@  int _hs_ToShortestLength(void); int _hs_Text_ToShortest(double value, uint16_t *buf);+int _hs_Text_ToShortestFloat(float value, uint16_t *buf); int _hs_ToShortest(double value, char *buf);+int _hs_ToShortestFloat(float value, char *buf); int _hs_ToFixedLength(void); int _hs_Text_ToFixed(double value, uint16_t *buf, int ndigits);+int _hs_Text_ToFixedFloat(float value, uint16_t *buf, int ndigits); int _hs_ToFixed(double value, char *buf, int ndigits);+int _hs_ToFixedFloat(float value, char *buf, int ndigits); int _hs_ToExponentialLength(void); int _hs_Text_ToExponential(double value, uint16_t *buf, int ndigits);+int _hs_Text_ToExponentialFloat(float value, uint16_t *buf, int ndigits); int _hs_ToExponential(double value, char *buf, int ndigits);+int _hs_ToExponentialFloat(float value, char *buf, int ndigits); int _hs_ToPrecisionLength(void); int _hs_Text_ToPrecision(double value, uint16_t *buf, int ndigits);+int _hs_Text_ToPrecisionFloat(float value, uint16_t *buf, int ndigits); int _hs_ToPrecision(double value, char *buf, int ndigits);+int _hs_ToPrecisionFloat(float value, char *buf, int ndigits);  #ifdef __cplusplus }
tests/Properties.hs view
@@ -1,8 +1,7 @@ import Test.Framework (Test, defaultMain, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty) import qualified Data.ByteString.Char8 as B-import qualified Data.Double.Conversion.ByteString as B-import qualified Data.Double.Conversion.Text as T+import qualified Data.Double.Conversion.Convertable as C import qualified Data.Text as T import qualified Regressions @@ -15,8 +14,8 @@  tests :: Test tests = testGroup "Properties" [-    testProperty "b_shortest" $ shortest (B.unpack . B.toShortest)-  , testProperty "t_shortest" $ shortest (T.unpack . T.toShortest)+    testProperty "b_shortest" $ shortest (B.unpack . C.toShortest)+  , testProperty "t_shortest" $ shortest (T.unpack . C.toShortest)   ]  main :: IO ()
tests/Regressions.hs view
@@ -3,7 +3,7 @@       tests     ) where -import Data.Double.Conversion.Text (toShortest)+import Data.Double.Conversion.Convertable import Test.HUnit (Assertion, assertEqual) import Data.Text (unpack) import Numeric (showFFloat)@@ -12,7 +12,7 @@  toShortest_overflow :: Assertion toShortest_overflow = do-  let val = -2.9658956854023756e-5+  let val = -2.9658956854023756e-5 :: Double   assertEqual "rendering a long number doesn't crash"               (showFFloat Nothing val "") (unpack (toShortest val))