Skip to content

Commit 3249d0c

Browse files
added shortest format mode to RealFloat that prints the shortest possible string
1 parent 7e11412 commit 3249d0c

File tree

1 file changed

+32
-4
lines changed

1 file changed

+32
-4
lines changed

Data/ByteString/Builder/RealFloat.hs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ module Data.ByteString.Builder.RealFloat
6868
, standardDefaultPrecision
6969
, scientific
7070
, generic
71+
, shortest
7172
) where
7273

7374
import Data.ByteString.Builder.Internal (Builder)
@@ -128,11 +129,18 @@ scientific = MkFloatFormat FScientific Nothing
128129
generic :: FloatFormat
129130
generic = 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
132139
data 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
163171
formatFloat :: FloatFormat -> Float -> Builder
164172
formatFloat (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 ->
206224
formatDouble :: FloatFormat -> Double -> Builder
207225
formatDouble (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

Comments
 (0)