    module Data.Csv.Conversion.Internal
        ( decimal
        , scientific
        , realFloat
        ) where

    import Data.ByteString.Builder (Builder, toLazyByteString, word8, char8,
                                    string8, byteString)
    import qualified Data.ByteString.Builder.Prim as BP
    import Data.ByteString.Builder.Scientific (scientificBuilder)
    import Data.Array.Base (unsafeAt)
    import Data.Array.IArray
    import qualified Data.ByteString as B
    import Data.Char (ord)
    import Data.Int
    import qualified Data.Monoid as Mon
    import Data.Scientific (Scientific)
    import Data.Word

    import Data.Csv.Util (toStrict)

    ------------------------------------------------------------------------
    -- Integers

    decimal :: Integral a => a -> B.ByteString
    decimal :: a -> ByteString
    decimal = ByteString -> ByteString
    toStrict (ByteString -> ByteString) -> (a -> ByteString) -> a -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> ByteString
    toLazyByteString (Builder -> ByteString) -> (a -> Builder) -> a -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> Builder
    forall a. Integral a => a -> Builder
    formatDecimal
    {-# INLINE decimal #-}

    -- TODO: Add an optimized version for Integer.

    formatDecimal :: Integral a => a -> Builder
    {-# RULES "formatDecimal/Int" formatDecimal = formatBoundedSigned
        :: Int -> Builder #-}
    {-# RULES "formatDecimal/Int8" formatDecimal = formatBoundedSigned
        :: Int8 -> Builder #-}
    {-# RULES "formatDecimal/Int16" formatDecimal = formatBoundedSigned
        :: Int16 -> Builder #-}
    {-# RULES "formatDecimal/Int32" formatDecimal = formatBoundedSigned
        :: Int32 -> Builder #-}
    {-# RULES "formatDecimal/Int64" formatDecimal = formatBoundedSigned
        :: Int64 -> Builder #-}
    {-# RULES "formatDecimal/Word" formatDecimal = formatPositive
        :: Word -> Builder #-}
    {-# RULES "formatDecimal/Word8" formatDecimal = formatPositive
        :: Word8 -> Builder #-}
    {-# RULES "formatDecimal/Word16" formatDecimal = formatPositive
        :: Word16 -> Builder #-}
    {-# RULES "formatDecimal/Word32" formatDecimal = formatPositive
        :: Word32 -> Builder #-}
    {-# RULES "formatDecimal/Word64" formatDecimal = formatPositive
        :: Word64 -> Builder #-}
    {-# NOINLINE formatDecimal #-}
    formatDecimal :: a -> Builder
    formatDecimal i :: a
    i
        | a
    i a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    < 0     = Builder
    minus Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<>
                      if a
    i a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= -128
                      then a -> Builder
    forall a. Integral a => a -> Builder
    formatPositive (-(a
    i a -> a -> a
    forall a. Integral a => a -> a -> a
    `quot` 10)) Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> a -> Builder
    forall a. Integral a => a -> Builder
    digit (-(a
    i a -> a -> a
    forall a. Integral a => a -> a -> a
    `rem` 10))
                      else a -> Builder
    forall a. Integral a => a -> Builder
    formatPositive (-a
    i)
        | Bool
    otherwise = a -> Builder
    forall a. Integral a => a -> Builder
    formatPositive a
    i

    formatBoundedSigned :: (Integral a, Bounded a) => a -> Builder
    {-# SPECIALIZE formatBoundedSigned :: Int -> Builder #-}
    {-# SPECIALIZE formatBoundedSigned :: Int8 -> Builder #-}
    {-# SPECIALIZE formatBoundedSigned :: Int16 -> Builder #-}
    {-# SPECIALIZE formatBoundedSigned :: Int32 -> Builder #-}
    {-# SPECIALIZE formatBoundedSigned :: Int64 -> Builder #-}
    formatBoundedSigned :: a -> Builder
    formatBoundedSigned i :: a
    i
        | a
    i a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    < 0     = Builder
    minus Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<>
                      if a
    i a -> a -> Bool
    forall a. Eq a => a -> a -> Bool
    == a
    forall a. Bounded a => a
    minBound
                      then a -> Builder
    forall a. Integral a => a -> Builder
    formatPositive (-(a
    i a -> a -> a
    forall a. Integral a => a -> a -> a
    `quot` 10)) Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> a -> Builder
    forall a. Integral a => a -> Builder
    digit (-(a
    i a -> a -> a
    forall a. Integral a => a -> a -> a
    `rem` 10))
                      else a -> Builder
    forall a. Integral a => a -> Builder
    formatPositive (-a
    i)
        | Bool
    otherwise = a -> Builder
    forall a. Integral a => a -> Builder
    formatPositive a
    i

    formatPositive :: Integral a => a -> Builder
    {-# SPECIALIZE formatPositive :: Int -> Builder #-}
    {-# SPECIALIZE formatPositive :: Int8 -> Builder #-}
    {-# SPECIALIZE formatPositive :: Int16 -> Builder #-}
    {-# SPECIALIZE formatPositive :: Int32 -> Builder #-}
    {-# SPECIALIZE formatPositive :: Int64 -> Builder #-}
    {-# SPECIALIZE formatPositive :: Word -> Builder #-}
    {-# SPECIALIZE formatPositive :: Word8 -> Builder #-}
    {-# SPECIALIZE formatPositive :: Word16 -> Builder #-}
    {-# SPECIALIZE formatPositive :: Word32 -> Builder #-}
    {-# SPECIALIZE formatPositive :: Word64 -> Builder #-}
    formatPositive :: a -> Builder
    formatPositive = a -> Builder
    forall a. Integral a => a -> Builder
    go
      where go :: a -> Builder
    go n :: a
    n | a
    n a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    < 10    = a -> Builder
    forall a. Integral a => a -> Builder
    digit a
    n
                 | Bool
    otherwise = a -> Builder
    go (a
    n a -> a -> a
    forall a. Integral a => a -> a -> a
    `quot` 10) Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> a -> Builder
    forall a. Integral a => a -> Builder
    digit (a
    n a -> a -> a
    forall a. Integral a => a -> a -> a
    `rem` 10)

    minus :: Builder
    minus :: Builder
    minus = Word8 -> Builder
    word8 45

    zero :: Word8
    zero :: Word8
    zero = 48

    digit :: Integral a => a -> Builder
    digit :: a -> Builder
    digit n :: a
    n = Word8 -> Builder
    word8 (Word8 -> Builder) -> Word8 -> Builder
    forall a b. (a -> b) -> a -> b
    $! Int -> Word8
    i2w (a -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    n)
    {-# INLINE digit #-}

    i2w :: Int -> Word8
    i2w :: Int -> Word8
    i2w i :: Int
    i = Word8
    zero Word8 -> Word8 -> Word8
    forall a. Num a => a -> a -> a
    + Int -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    i
    {-# INLINE i2w #-}

    ------------------------------------------------------------------------
    -- Floating point numbers

    scientific :: Scientific -> B.ByteString
    scientific :: Scientific -> ByteString
    scientific = ByteString -> ByteString
    toStrict (ByteString -> ByteString)
    -> (Scientific -> ByteString) -> Scientific -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> ByteString
    toLazyByteString (Builder -> ByteString)
    -> (Scientific -> Builder) -> Scientific -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Scientific -> Builder
    scientificBuilder
    {-# INLINE scientific #-}

    realFloat :: RealFloat a => a -> B.ByteString
    {-# SPECIALIZE realFloat :: Float -> B.ByteString #-}
    {-# SPECIALIZE realFloat :: Double -> B.ByteString #-}
    realFloat :: a -> ByteString
    realFloat = ByteString -> ByteString
    toStrict (ByteString -> ByteString) -> (a -> ByteString) -> a -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> ByteString
    toLazyByteString (Builder -> ByteString) -> (a -> Builder) -> a -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FPFormat -> a -> Builder
    forall a. RealFloat a => FPFormat -> a -> Builder
    formatRealFloat FPFormat
    Generic

    -- | Control the rendering of floating point numbers.
    data FPFormat = Exponent
                  -- ^ Scientific notation (e.g. @2.3e123@).
                  | Fixed
                  -- ^ Standard decimal notation.
                  | Generic
                  -- ^ Use decimal notation for values between @0.1@ and
                  -- @9,999,999@, and scientific notation otherwise.
                    deriving (Int -> FPFormat
    FPFormat -> Int
    FPFormat -> [FPFormat]
    FPFormat -> FPFormat
    FPFormat -> FPFormat -> [FPFormat]
    FPFormat -> FPFormat -> FPFormat -> [FPFormat]
    (FPFormat -> FPFormat)
    -> (FPFormat -> FPFormat)
    -> (Int -> FPFormat)
    -> (FPFormat -> Int)
    -> (FPFormat -> [FPFormat])
    -> (FPFormat -> FPFormat -> [FPFormat])
    -> (FPFormat -> FPFormat -> [FPFormat])
    -> (FPFormat -> FPFormat -> FPFormat -> [FPFormat])
    -> Enum FPFormat
    forall a.
    (a -> a)
    -> (a -> a)
    -> (Int -> a)
    -> (a -> Int)
    -> (a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> a -> [a])
    -> Enum a
    enumFromThenTo :: FPFormat -> FPFormat -> FPFormat -> [FPFormat]
    $cenumFromThenTo :: FPFormat -> FPFormat -> FPFormat -> [FPFormat]
    enumFromTo :: FPFormat -> FPFormat -> [FPFormat]
    $cenumFromTo :: FPFormat -> FPFormat -> [FPFormat]
    enumFromThen :: FPFormat -> FPFormat -> [FPFormat]
    $cenumFromThen :: FPFormat -> FPFormat -> [FPFormat]
    enumFrom :: FPFormat -> [FPFormat]
    $cenumFrom :: FPFormat -> [FPFormat]
    fromEnum :: FPFormat -> Int
    $cfromEnum :: FPFormat -> Int
    toEnum :: Int -> FPFormat
    $ctoEnum :: Int -> FPFormat
    pred :: FPFormat -> FPFormat
    $cpred :: FPFormat -> FPFormat
    succ :: FPFormat -> FPFormat
    $csucc :: FPFormat -> FPFormat
    Enum, ReadPrec [FPFormat]
    ReadPrec FPFormat
    Int -> ReadS FPFormat
    ReadS [FPFormat]
    (Int -> ReadS FPFormat)
    -> ReadS [FPFormat]
    -> ReadPrec FPFormat
    -> ReadPrec [FPFormat]
    -> Read FPFormat
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    readListPrec :: ReadPrec [FPFormat]
    $creadListPrec :: ReadPrec [FPFormat]
    readPrec :: ReadPrec FPFormat
    $creadPrec :: ReadPrec FPFormat
    readList :: ReadS [FPFormat]
    $creadList :: ReadS [FPFormat]
    readsPrec :: Int -> ReadS FPFormat
    $creadsPrec :: Int -> ReadS FPFormat
    Read, Int -> FPFormat -> ShowS
    [FPFormat] -> ShowS
    FPFormat -> String
    (Int -> FPFormat -> ShowS)
    -> (FPFormat -> String) -> ([FPFormat] -> ShowS) -> Show FPFormat
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [FPFormat] -> ShowS
    $cshowList :: [FPFormat] -> ShowS
    show :: FPFormat -> String
    $cshow :: FPFormat -> String
    showsPrec :: Int -> FPFormat -> ShowS
    $cshowsPrec :: Int -> FPFormat -> ShowS
    Show)

    formatRealFloat :: RealFloat a => FPFormat -> a -> Builder
    {-# SPECIALIZE formatRealFloat :: FPFormat -> Float -> Builder #-}
    {-# SPECIALIZE formatRealFloat :: FPFormat -> Double -> Builder #-}
    formatRealFloat :: FPFormat -> a -> Builder
    formatRealFloat fmt :: FPFormat
    fmt x :: a
    x
       | a -> Bool
    forall a. RealFloat a => a -> Bool
    isNaN a
    x                   = String -> Builder
    string8 "NaN"
       | a -> Bool
    forall a. RealFloat a => a -> Bool
    isInfinite a
    x              = if a
    x a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    < 0
                                     then String -> Builder
    string8 "-Infinity"
                                     else String -> Builder
    string8 "Infinity"
       | a
    x a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    < 0 Bool -> Bool -> Bool
    || a -> Bool
    forall a. RealFloat a => a -> Bool
    isNegativeZero a
    x = Builder
    minus Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> FPFormat -> ([Int], Int) -> Builder
    doFmt FPFormat
    fmt (a -> ([Int], Int)
    forall a. RealFloat a => a -> ([Int], Int)
    floatToDigits (-a
    x))
       | Bool
    otherwise                 = FPFormat -> ([Int], Int) -> Builder
    doFmt FPFormat
    fmt (a -> ([Int], Int)
    forall a. RealFloat a => a -> ([Int], Int)
    floatToDigits a
    x)
     where
      doFmt :: FPFormat -> ([Int], Int) -> Builder
    doFmt format :: FPFormat
    format (is :: [Int]
    is, e :: Int
    e) =
        let ds :: [Word8]
    ds = (Int -> Word8) -> [Int] -> [Word8]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> Word8
    i2d [Int]
    is in
        case FPFormat
    format of
         Generic ->
          FPFormat -> ([Int], Int) -> Builder
    doFmt (if Int
    e Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < 0 Bool -> Bool -> Bool
    || Int
    e Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > 7 then FPFormat
    Exponent else FPFormat
    Fixed)
                ([Int]
    is,Int
    e)
         Exponent ->
            let show_e' :: Builder
    show_e' = Int -> Builder
    forall a. Integral a => a -> Builder
    formatDecimal (Int
    eInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -1) in
            case [Word8]
    ds of
              [48]    -> String -> Builder
    string8 "0.0e0"
              [d :: Word8
    d]     -> Word8 -> Builder
    word8 Word8
    d Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> String -> Builder
    string8 ".0e" Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> Builder
    show_e'
              (d :: Word8
    d:ds' :: [Word8]
    ds') -> Word8 -> Builder
    word8 Word8
    d Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> Char -> Builder
    char8 '.' Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> [Word8] -> Builder
    word8s [Word8]
    ds' Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<>
                         Char -> Builder
    char8 'e' Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> Builder
    show_e'
              []      -> String -> Builder
    forall a. HasCallStack => String -> a
    error "formatRealFloat/doFmt/Exponent: []"
         Fixed
              | Int
    e Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 0    -> String -> Builder
    string8 "0." Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<>
                             ByteString -> Builder
    byteString (Int -> Word8 -> ByteString
    B.replicate (-Int
    e) Word8
    zero) Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<>
                             [Word8] -> Builder
    word8s [Word8]
    ds
              | Bool
    otherwise ->
                 let
                    f :: a -> [Word8] -> [Word8] -> Builder
    f 0 s :: [Word8]
    s    rs :: [Word8]
    rs  = [Word8] -> Builder
    mk0 ([Word8] -> [Word8]
    forall a. [a] -> [a]
    reverse [Word8]
    s) Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> Char -> Builder
    char8 '.' Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> [Word8] -> Builder
    mk0 [Word8]
    rs
                    f n :: a
    n s :: [Word8]
    s    []  = a -> [Word8] -> [Word8] -> Builder
    f (a
    na -> a -> a
    forall a. Num a => a -> a -> a
    -1) (Word8
    zeroWord8 -> [Word8] -> [Word8]
    forall a. a -> [a] -> [a]
    :[Word8]
    s) []
                    f n :: a
    n s :: [Word8]
    s (r :: Word8
    r:rs :: [Word8]
    rs) = a -> [Word8] -> [Word8] -> Builder
    f (a
    na -> a -> a
    forall a. Num a => a -> a -> a
    -1) (Word8
    rWord8 -> [Word8] -> [Word8]
    forall a. a -> [a] -> [a]
    :[Word8]
    s) [Word8]
    rs
                 in
                    Int -> [Word8] -> [Word8] -> Builder
    forall a. (Eq a, Num a) => a -> [Word8] -> [Word8] -> Builder
    f Int
    e [] [Word8]
    ds
           where mk0 :: [Word8] -> Builder
    mk0 ls :: [Word8]
    ls = case [Word8]
    ls of { [] -> Word8 -> Builder
    word8 Word8
    zero ; _ -> [Word8] -> Builder
    word8s [Word8]
    ls}

    -- Based on "Printing Floating-Point Numbers Quickly and Accurately"
    -- by R.G. Burger and R.K. Dybvig in PLDI 96.
    -- This version uses a much slower logarithm estimator. It should be improved.

    -- | 'floatToDigits' takes a base and a non-negative 'RealFloat' number,
    -- and returns a list of digits and an exponent.
    -- In particular, if @x>=0@, and
    --
    -- > floatToDigits base x = ([d1,d2,...,dn], e)
    --
    -- then
    --
    --      (1) @n >= 1@
    --
    --      (2) @x = 0.d1d2...dn * (base**e)@
    --
    --      (3) @0 <= di <= base-1@

    floatToDigits :: (RealFloat a) => a -> ([Int], Int)
    {-# SPECIALIZE floatToDigits :: Float -> ([Int], Int) #-}
    {-# SPECIALIZE floatToDigits :: Double -> ([Int], Int) #-}
    floatToDigits :: a -> ([Int], Int)
    floatToDigits 0 = ([0], 0)
    floatToDigits x :: a
    x =
     let
      (f0 :: Integer
    f0, e0 :: Int
    e0) = a -> (Integer, Int)
    forall a. RealFloat a => a -> (Integer, Int)
    decodeFloat a
    x
      (minExp0 :: Int
    minExp0, _) = a -> (Int, Int)
    forall a. RealFloat a => a -> (Int, Int)
    floatRange a
    x
      p :: Int
    p = a -> Int
    forall a. RealFloat a => a -> Int
    floatDigits a
    x
      b :: Integer
    b = a -> Integer
    forall a. RealFloat a => a -> Integer
    floatRadix a
    x
      minExp :: Int
    minExp = Int
    minExp0 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    p -- the real minimum exponent
      -- Haskell requires that f be adjusted so denormalized numbers
      -- will have an impossibly low exponent.  Adjust for this.
      (f :: Integer
    f, e :: Int
    e) =
       let n :: Int
    n = Int
    minExp Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    e0 in
       if Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > 0 then (Integer
    f0 Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `quot` (Integer -> Int -> Integer
    expt Integer
    b Int
    n), Int
    e0Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    n) else (Integer
    f0, Int
    e0)
      (r :: Integer
    r, s :: Integer
    s, mUp :: Integer
    mUp, mDn :: Integer
    mDn) =
       if Int
    e Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 0 then
        let be :: Integer
    be = Integer -> Int -> Integer
    expt Integer
    b Int
    e in
        if Integer
    f Integer -> Integer -> Bool
    forall a. Eq a => a -> a -> Bool
    == Integer -> Int -> Integer
    expt Integer
    b (Int
    pInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -1) then
          (Integer
    fInteger -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *Integer
    beInteger -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *Integer
    bInteger -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *2, 2Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *Integer
    b, Integer
    beInteger -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *Integer
    b, Integer
    be)     -- according to Burger and Dybvig
        else
          (Integer
    fInteger -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *Integer
    beInteger -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *2, 2, Integer
    be, Integer
    be)
       else
        if Int
    e Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    minExp Bool -> Bool -> Bool
    && Integer
    f Integer -> Integer -> Bool
    forall a. Eq a => a -> a -> Bool
    == Integer -> Int -> Integer
    expt Integer
    b (Int
    pInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -1) then
          (Integer
    fInteger -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *Integer
    bInteger -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *2, Integer -> Int -> Integer
    expt Integer
    b (-Int
    eInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +1)Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *2, Integer
    b, 1)
        else
          (Integer
    fInteger -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *2, Integer -> Int -> Integer
    expt Integer
    b (-Int
    e)Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    *2, 1, 1)
      k :: Int
      k :: Int
    k =
       let
        k0 :: Int
        k0 :: Int
    k0 =
         if Integer
    b Integer -> Integer -> Bool
    forall a. Eq a => a -> a -> Bool
    == 2 then
            -- logBase 10 2 is very slightly larger than 8651/28738
            -- (about 5.3558e-10), so if log x >= 0, the approximation
            -- k1 is too small, hence we add one and need one fixup step less.
            -- If log x < 0, the approximation errs rather on the high side.
            -- That is usually more than compensated for by ignoring the
            -- fractional part of logBase 2 x, but when x is a power of 1/2
            -- or slightly larger and the exponent is a multiple of the
            -- denominator of the rational approximation to logBase 10 2,
            -- k1 is larger than logBase 10 x. If k1 > 1 + logBase 10 x,
            -- we get a leading zero-digit we don't want.
            -- With the approximation 3/10, this happened for
            -- 0.5^1030, 0.5^1040, ..., 0.5^1070 and values close above.
            -- The approximation 8651/28738 guarantees k1 < 1 + logBase 10 x
            -- for IEEE-ish floating point types with exponent fields
            -- <= 17 bits and mantissae of several thousand bits, earlier
            -- convergents to logBase 10 2 would fail for long double.
            -- Using quot instead of div is a little faster and requires
            -- fewer fixup steps for negative lx.
            let lx :: Int
    lx = Int
    p Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 1 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    e0
                k1 :: Int
    k1 = (Int
    lx Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * 8651) Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `quot` 28738
            in if Int
    lx Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 0 then Int
    k1 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + 1 else Int
    k1
         else
            -- f :: Integer, log :: Float -> Float,
            --               ceiling :: Float -> Int
            Float -> Int
    forall a b. (RealFrac a, Integral b) => a -> b
    ceiling ((Float -> Float
    forall a. Floating a => a -> a
    log (Integer -> Float
    forall a. Num a => Integer -> a
    fromInteger (Integer
    fInteger -> Integer -> Integer
    forall a. Num a => a -> a -> a
    +1) :: Float) Float -> Float -> Float
    forall a. Num a => a -> a -> a
    +
                     Int -> Float
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    e Float -> Float -> Float
    forall a. Num a => a -> a -> a
    * Float -> Float
    forall a. Floating a => a -> a
    log (Integer -> Float
    forall a. Num a => Integer -> a
    fromInteger Integer
    b)) Float -> Float -> Float
    forall a. Fractional a => a -> a -> a
    /
                       Float -> Float
    forall a. Floating a => a -> a
    log 10)
    --WAS:            fromInt e * log (fromInteger b))

        fixup :: Int -> Int
    fixup n :: Int
    n =
          if Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 0 then
            if Integer
    r Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    + Integer
    mUp Integer -> Integer -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Integer -> Int -> Integer
    expt 10 Int
    n Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    s then Int
    n else Int -> Int
    fixup (Int
    nInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +1)
          else
            if Integer -> Int -> Integer
    expt 10 (-Int
    n) Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * (Integer
    r Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    + Integer
    mUp) Integer -> Integer -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Integer
    s then Int
    n else Int -> Int
    fixup (Int
    nInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +1)
       in
       Int -> Int
    fixup Int
    k0

      gen :: [t] -> t -> t -> t -> t -> [t]
    gen ds :: [t]
    ds rn :: t
    rn sN :: t
    sN mUpN :: t
    mUpN mDnN :: t
    mDnN =
       let
        (dn :: t
    dn, rn' :: t
    rn') = (t
    rn t -> t -> t
    forall a. Num a => a -> a -> a
    * 10) t -> t -> (t, t)
    forall a. Integral a => a -> a -> (a, a)
    `quotRem` t
    sN
        mUpN' :: t
    mUpN' = t
    mUpN t -> t -> t
    forall a. Num a => a -> a -> a
    * 10
        mDnN' :: t
    mDnN' = t
    mDnN t -> t -> t
    forall a. Num a => a -> a -> a
    * 10
       in
       case (t
    rn' t -> t -> Bool
    forall a. Ord a => a -> a -> Bool
    < t
    mDnN', t
    rn' t -> t -> t
    forall a. Num a => a -> a -> a
    + t
    mUpN' t -> t -> Bool
    forall a. Ord a => a -> a -> Bool
    > t
    sN) of
        (True,  False) -> t
    dn t -> [t] -> [t]
    forall a. a -> [a] -> [a]
    : [t]
    ds
        (False, True)  -> t
    dnt -> t -> t
    forall a. Num a => a -> a -> a
    +1 t -> [t] -> [t]
    forall a. a -> [a] -> [a]
    : [t]
    ds
        (True,  True)  -> if t
    rn' t -> t -> t
    forall a. Num a => a -> a -> a
    * 2 t -> t -> Bool
    forall a. Ord a => a -> a -> Bool
    < t
    sN then t
    dn t -> [t] -> [t]
    forall a. a -> [a] -> [a]
    : [t]
    ds else t
    dnt -> t -> t
    forall a. Num a => a -> a -> a
    +1 t -> [t] -> [t]
    forall a. a -> [a] -> [a]
    : [t]
    ds
        (False, False) -> [t] -> t -> t -> t -> t -> [t]
    gen (t
    dnt -> [t] -> [t]
    forall a. a -> [a] -> [a]
    :[t]
    ds) t
    rn' t
    sN t
    mUpN' t
    mDnN'

      rds :: [Integer]
    rds =
       if Int
    k Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= 0 then
          [Integer] -> Integer -> Integer -> Integer -> Integer -> [Integer]
    forall t. Integral t => [t] -> t -> t -> t -> t -> [t]
    gen [] Integer
    r (Integer
    s Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer -> Int -> Integer
    expt 10 Int
    k) Integer
    mUp Integer
    mDn
       else
         let bk :: Integer
    bk = Integer -> Int -> Integer
    expt 10 (-Int
    k) in
         [Integer] -> Integer -> Integer -> Integer -> Integer -> [Integer]
    forall t. Integral t => [t] -> t -> t -> t -> t -> [t]
    gen [] (Integer
    r Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    bk) Integer
    s (Integer
    mUp Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    bk) (Integer
    mDn Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    * Integer
    bk)
     in
     ((Integer -> Int) -> [Integer] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    map Integer -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral ([Integer] -> [Integer]
    forall a. [a] -> [a]
    reverse [Integer]
    rds), Int
    k)

    -- Exponentiation with a cache for the most common numbers.
    minExpt, maxExpt :: Int
    minExpt :: Int
    minExpt = 0
    maxExpt :: Int
    maxExpt = 1100

    expt :: Integer -> Int -> Integer
    expt :: Integer -> Int -> Integer
    expt base :: Integer
    base n :: Int
    n
        | Integer
    base Integer -> Integer -> Bool
    forall a. Eq a => a -> a -> Bool
    == 2 Bool -> Bool -> Bool
    && Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    minExpt Bool -> Bool -> Bool
    && Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    maxExpt = Array Int Integer
    expts Array Int Integer -> Int -> Integer
    forall (a :: * -> * -> *) e i.
    (IArray a e, Ix i) =>
    a i e -> Int -> e
    `unsafeAt` Int
    n
        | Integer
    base Integer -> Integer -> Bool
    forall a. Eq a => a -> a -> Bool
    == 10 Bool -> Bool -> Bool
    && Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    maxExpt10              = Array Int Integer
    expts10 Array Int Integer -> Int -> Integer
    forall (a :: * -> * -> *) e i.
    (IArray a e, Ix i) =>
    a i e -> Int -> e
    `unsafeAt` Int
    n
        | Bool
    otherwise                                 = Integer
    baseInteger -> Int -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^Int
    n

    expts :: Array Int Integer
    expts :: Array Int Integer
    expts = (Int, Int) -> [(Int, Integer)] -> Array Int Integer
    forall (a :: * -> * -> *) e i.
    (IArray a e, Ix i) =>
    (i, i) -> [(i, e)] -> a i e
    array (Int
    minExpt,Int
    maxExpt) [(Int
    n,2Integer -> Int -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^Int
    n) | Int
    n <- [Int
    minExpt .. Int
    maxExpt]]

    maxExpt10 :: Int
    maxExpt10 :: Int
    maxExpt10 = 324

    expts10 :: Array Int Integer
    expts10 :: Array Int Integer
    expts10 = (Int, Int) -> [(Int, Integer)] -> Array Int Integer
    forall (a :: * -> * -> *) e i.
    (IArray a e, Ix i) =>
    (i, i) -> [(i, e)] -> a i e
    array (Int
    minExpt,Int
    maxExpt10) [(Int
    n,10Integer -> Int -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^Int
    n) | Int
    n <- [Int
    minExpt .. Int
    maxExpt10]]

    -- | Unsafe conversion for decimal digits.
    {-# INLINE i2d #-}
    i2d :: Int -> Word8
    i2d :: Int -> Word8
    i2d i :: Int
    i = Int -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Char -> Int
    ord '0' Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    i)

    -- | Word8 list rendering
    word8s :: [Word8] -> Builder
    word8s :: [Word8] -> Builder
    word8s = FixedPrim Word8 -> [Word8] -> Builder
    forall a. FixedPrim a -> [a] -> Builder
    BP.primMapListFixed FixedPrim Word8
    BP.word8