@@ -68,6 +68,7 @@ module Data.ByteString.Builder.RealFloat
6868 , standardDefaultPrecision
6969 , scientific
7070 , generic
71+ , shortest
7172 ) where
7273
7374import Data.ByteString.Builder.Internal (Builder )
@@ -128,11 +129,18 @@ scientific = MkFloatFormat FScientific Nothing
128129generic :: FloatFormat
129130generic = MkFloatFormat FGeneric Nothing
130131
132+ -- | Standard or scientific notation depending on which uses the least number of charabers.
133+ --
134+ -- @since ????
135+ shortest :: FloatFormat
136+ shortest = MkFloatFormat FShortest Nothing
137+
131138-- | ByteString float-to-string format
132139data FormatMode
133140 = FScientific -- ^ scientific notation
134141 | FStandard -- ^ standard notation with `Maybe Int` digits after the decimal
135142 | FGeneric -- ^ dispatches to scientific or standard notation based on the exponent
143+ | FShortest -- ^ the actual shortest length string of either standard notation or scientific notation
136144 deriving Show
137145
138146-- TODO: support precision argument for FGeneric and FScientific
@@ -163,8 +171,10 @@ data FormatMode
163171formatFloat :: FloatFormat -> Float -> Builder
164172formatFloat (MkFloatFormat fmt prec) = \ f ->
165173 let (RF. FloatingDecimal m e) = RF. f2Intermediate f
166- e' = R. int32ToInt e + R. decimalLength9 m in
167- case fmt of
174+ e' = e'' + olength
175+ e'' = R. int32ToInt e
176+ olength = R. decimalLength9 m
177+ in case fmt of
168178 FGeneric ->
169179 case specialStr f of
170180 Just b -> b
@@ -177,6 +187,14 @@ formatFloat (MkFloatFormat fmt prec) = \f ->
177187 case specialStr f of
178188 Just b -> b
179189 Nothing -> sign f `mappend` showStandard (R. word32ToWord64 m) e' prec
190+ FShortest ->
191+ case specialStr f of
192+ Just b -> b
193+ Nothing ->
194+ if e'' >= 0 && (olength + 2 >= e'' || olength == 1 && e'' <= 2 )
195+ || e'' < 0 && (olength + e'' >= (- 3 ) || olength == 1 && e'' >= (- 2 ))
196+ then sign f `mappend` showStandard (R. word32ToWord64 m) e' prec
197+ else BP. primBounded (R. toCharsScientific (f < 0 ) m e) ()
180198
181199-- TODO: support precision argument for FGeneric and FScientific
182200-- | Returns a rendered Double. Returns the \'shortest\' representation in
@@ -206,8 +224,10 @@ formatFloat (MkFloatFormat fmt prec) = \f ->
206224formatDouble :: FloatFormat -> Double -> Builder
207225formatDouble (MkFloatFormat fmt prec) = \ f ->
208226 let (RD. FloatingDecimal m e) = RD. d2Intermediate f
209- e' = R. int32ToInt e + R. decimalLength17 m in
210- case fmt of
227+ e' = e'' + olength
228+ e'' = R. int32ToInt e
229+ olength = R. decimalLength17 m
230+ in case fmt of
211231 FGeneric ->
212232 case specialStr f of
213233 Just b -> b
@@ -220,6 +240,14 @@ formatDouble (MkFloatFormat fmt prec) = \f ->
220240 case specialStr f of
221241 Just b -> b
222242 Nothing -> sign f `mappend` showStandard m e' prec
243+ FShortest ->
244+ case specialStr f of
245+ Just b -> b
246+ Nothing ->
247+ if e'' >= 0 && (olength + 2 >= e'' || olength == 1 && e'' <= 2 )
248+ || e'' < 0 && (olength + e'' >= (- 3 ) || olength == 1 && e'' >= (- 2 ))
249+ then sign f `mappend` showStandard m e' prec
250+ else BP. primBounded (R. toCharsScientific (f < 0 ) m e) ()
223251
224252-- | Char7 encode a 'Char'.
225253{-# INLINE char7 #-}
0 commit comments