diff --git a/Data/ByteString/Builder/RealFloat.hs b/Data/ByteString/Builder/RealFloat.hs index 1fef16a0b..9035ae157 100644 --- a/Data/ByteString/Builder/RealFloat.hs +++ b/Data/ByteString/Builder/RealFloat.hs @@ -68,6 +68,7 @@ module Data.ByteString.Builder.RealFloat , standardDefaultPrecision , scientific , generic + , shortest ) where import Data.ByteString.Builder.Internal (Builder) @@ -128,11 +129,18 @@ scientific = MkFloatFormat FScientific Nothing generic :: FloatFormat generic = MkFloatFormat FGeneric Nothing +-- | Standard or scientific notation depending on which uses the least number of charabers. +-- +-- @since ???? +shortest :: FloatFormat +shortest = MkFloatFormat FShortest Nothing + -- | ByteString float-to-string format data FormatMode = FScientific -- ^ scientific notation | FStandard -- ^ standard notation with `Maybe Int` digits after the decimal | FGeneric -- ^ dispatches to scientific or standard notation based on the exponent + | FShortest -- ^ the actual shortest length string of either standard notation or scientific notation deriving Show -- TODO: support precision argument for FGeneric and FScientific @@ -163,8 +171,10 @@ data FormatMode formatFloat :: FloatFormat -> Float -> Builder formatFloat (MkFloatFormat fmt prec) = \f -> let (RF.FloatingDecimal m e) = RF.f2Intermediate f - e' = R.int32ToInt e + R.decimalLength9 m in - case fmt of + e' = e'' + olength + e'' = R.int32ToInt e + olength = R.decimalLength9 m + in case fmt of FGeneric -> case specialStr f of Just b -> b @@ -177,6 +187,14 @@ formatFloat (MkFloatFormat fmt prec) = \f -> case specialStr f of Just b -> b Nothing -> sign f `mappend` showStandard (R.word32ToWord64 m) e' prec + FShortest -> + case specialStr f of + Just b -> b + Nothing -> + if e'' >= 0 && (olength + 2 >= e'' || olength == 1 && e'' <= 2) + || e'' < 0 && (olength + e'' >= (-3) || olength == 1 && e'' >= (-2)) + then sign f `mappend` showStandard (R.word32ToWord64 m) e' prec + else BP.primBounded (R.toCharsScientific (f < 0) m e) () -- TODO: support precision argument for FGeneric and FScientific -- | Returns a rendered Double. Returns the \'shortest\' representation in @@ -206,8 +224,10 @@ formatFloat (MkFloatFormat fmt prec) = \f -> formatDouble :: FloatFormat -> Double -> Builder formatDouble (MkFloatFormat fmt prec) = \f -> let (RD.FloatingDecimal m e) = RD.d2Intermediate f - e' = R.int32ToInt e + R.decimalLength17 m in - case fmt of + e' = e'' + olength + e'' = R.int32ToInt e + olength = R.decimalLength17 m + in case fmt of FGeneric -> case specialStr f of Just b -> b @@ -220,6 +240,14 @@ formatDouble (MkFloatFormat fmt prec) = \f -> case specialStr f of Just b -> b Nothing -> sign f `mappend` showStandard m e' prec + FShortest -> + case specialStr f of + Just b -> b + Nothing -> + if e'' >= 0 && (olength + 2 >= e'' || olength == 1 && e'' <= 2) + || e'' < 0 && (olength + e'' >= (-3) || olength == 1 && e'' >= (-2)) + then sign f `mappend` showStandard m e' prec + else BP.primBounded (R.toCharsScientific (f < 0) m e) () -- | Char7 encode a 'Char'. {-# INLINE char7 #-}