{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns, MagicHash #-}
-- |
-- Module      : Data.ByteString.Builder.RealFloat.F2S
-- Copyright   : (c) Lawrence Wu 2021
-- License     : BSD-style
-- Maintainer  : lawrencejwu@gmail.com
--
-- Implementation of float-to-string conversion

module Data.ByteString.Builder.RealFloat.F2S
    ( FloatingDecimal(..)
    , f2s
    , f2Intermediate
    ) where

import Control.Arrow (first)
import Data.Bits ((.|.), (.&.), unsafeShiftL, unsafeShiftR)
import Data.ByteString.Builder.Internal (Builder)
import Data.ByteString.Builder.Prim (primBounded)
import Data.ByteString.Builder.RealFloat.Internal
import GHC.Int (Int32(..))
import GHC.Word (Word32(..), Word64(..))

#if !PURE_HASKELL
import GHC.Ptr (Ptr(..))
#endif

-- See Data.ByteString.Builder.RealFloat.TableGenerator for a high-level
-- explanation of the ryu algorithm

#if !PURE_HASKELL
-- | Table of 2^k / 5^q + 1
--
-- > fmap (finv float_pow5_inv_bitcount) [0..float_max_inv_split]
foreign import ccall "&hs_bytestring_float_pow5_inv_split"
  float_pow5_inv_split :: Ptr Word64

-- | Table of 5^(-e2-q) / 2^k + 1
--
-- > fmap (fnorm float_pow5_bitcount) [0..float_max_split]
foreign import ccall "&hs_bytestring_float_pow5_split"
  float_pow5_split :: Ptr Word64
#endif

-- | Number of mantissa bits of a 32-bit float. The number of significant bits
-- (floatDigits (undefined :: Float)) is 24 since we have a leading 1 for
-- normal floats and 0 for subnormal floats
float_mantissa_bits :: Int
float_mantissa_bits :: Int
float_mantissa_bits = Int
23

-- | Number of exponent bits of a 32-bit float
float_exponent_bits :: Int
float_exponent_bits :: Int
float_exponent_bits = Int
8

-- | Bias in encoded 32-bit float representation (2^7 - 1)
float_bias :: Int
float_bias :: Int
float_bias = Int
127

data FloatingDecimal = FloatingDecimal
  { FloatingDecimal -> Word32
fmantissa :: !Word32
  , FloatingDecimal -> Int32
fexponent :: !Int32
  } deriving (Int -> FloatingDecimal -> ShowS
[FloatingDecimal] -> ShowS
FloatingDecimal -> String
(Int -> FloatingDecimal -> ShowS)
-> (FloatingDecimal -> String)
-> ([FloatingDecimal] -> ShowS)
-> Show FloatingDecimal
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FloatingDecimal -> ShowS
showsPrec :: Int -> FloatingDecimal -> ShowS
$cshow :: FloatingDecimal -> String
show :: FloatingDecimal -> String
$cshowList :: [FloatingDecimal] -> ShowS
showList :: [FloatingDecimal] -> ShowS
Show, FloatingDecimal -> FloatingDecimal -> Bool
(FloatingDecimal -> FloatingDecimal -> Bool)
-> (FloatingDecimal -> FloatingDecimal -> Bool)
-> Eq FloatingDecimal
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FloatingDecimal -> FloatingDecimal -> Bool
== :: FloatingDecimal -> FloatingDecimal -> Bool
$c/= :: FloatingDecimal -> FloatingDecimal -> Bool
/= :: FloatingDecimal -> FloatingDecimal -> Bool
Eq)

-- | Multiply a 32-bit number with a 64-bit number while keeping the upper 64
-- bits. Then shift by specified amount minus 32
mulShift32 :: Word32 -> Word64 -> Int -> Word32
mulShift32 :: Word32 -> Word64 -> Int -> Word32
mulShift32 Word32
m Word64
factor Int
shift =
  let factorLo :: Word64
factorLo = Word64
factor Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Int -> Word64
forall a. (Bits a, Integral a) => Int -> a
mask Int
32
      factorHi :: Word64
factorHi = Word64
factor Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
32
      bits0 :: Word64
bits0 = Word32 -> Word64
word32ToWord64 Word32
m Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
factorLo
      bits1 :: Word64
bits1 = Word32 -> Word64
word32ToWord64 Word32
m Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
factorHi
      total :: Word64
total  = (Word64
bits0 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
32) Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
bits1
   in Word64 -> Word32
word64ToWord32 (Word64 -> Word32) -> Word64 -> Word32
forall a b. (a -> b) -> a -> b
$ Word64
total Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` (Int
shift Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
32)

-- | Index into the 64-bit word lookup table float_pow5_inv_split
get_float_pow5_inv_split :: Int -> Word64
#if !PURE_HASKELL
get_float_pow5_inv_split :: Int -> Word64
get_float_pow5_inv_split = Ptr Word64 -> Int -> Word64
getWord64At Ptr Word64
float_pow5_inv_split
#else
-- > putStr $ case64 (finv float_pow5_inv_bitcount) [0..float_max_inv_split]
get_float_pow5_inv_split i = case i of
  0  -> 0x800000000000001
  1  -> 0x666666666666667
  2  -> 0x51eb851eb851eb9
  3  -> 0x4189374bc6a7efa
  4  -> 0x68db8bac710cb2a
  5  -> 0x53e2d6238da3c22
  6  -> 0x431bde82d7b634e
  7  -> 0x6b5fca6af2bd216
  8  -> 0x55e63b88c230e78
  9  -> 0x44b82fa09b5a52d
  10 -> 0x6df37f675ef6eae
  11 -> 0x57f5ff85e592558
  12 -> 0x465e6604b7a8447
  13 -> 0x709709a125da071
  14 -> 0x5a126e1a84ae6c1
  15 -> 0x480ebe7b9d58567
  16 -> 0x734aca5f6226f0b
  17 -> 0x5c3bd5191b525a3
  18 -> 0x49c97747490eae9
  19 -> 0x760f253edb4ab0e
  20 -> 0x5e72843249088d8
  21 -> 0x4b8ed0283a6d3e0
  22 -> 0x78e480405d7b966
  23 -> 0x60b6cd004ac9452
  24 -> 0x4d5f0a66a23a9db
  25 -> 0x7bcb43d769f762b
  26 -> 0x63090312bb2c4ef
  27 -> 0x4f3a68dbc8f03f3
  28 -> 0x7ec3daf94180651
  29 -> 0x65697bfa9acd1da
  _  -> 0x51212ffbaf0a7e2
#endif

-- | Index into the 64-bit word lookup table float_pow5_split
get_float_pow5_split :: Int -> Word64
#if !PURE_HASKELL
get_float_pow5_split :: Int -> Word64
get_float_pow5_split = Ptr Word64 -> Int -> Word64
getWord64At Ptr Word64
float_pow5_split
#else
-- > putStr $ case64 (fnorm float_pow5_bitcount) [0..float_max_split]
get_float_pow5_split i = case i of
  0  -> 0x1000000000000000
  1  -> 0x1400000000000000
  2  -> 0x1900000000000000
  3  -> 0x1f40000000000000
  4  -> 0x1388000000000000
  5  -> 0x186a000000000000
  6  -> 0x1e84800000000000
  7  -> 0x1312d00000000000
  8  -> 0x17d7840000000000
  9  -> 0x1dcd650000000000
  10 -> 0x12a05f2000000000
  11 -> 0x174876e800000000
  12 -> 0x1d1a94a200000000
  13 -> 0x12309ce540000000
  14 -> 0x16bcc41e90000000
  15 -> 0x1c6bf52634000000
  16 -> 0x11c37937e0800000
  17 -> 0x16345785d8a00000
  18 -> 0x1bc16d674ec80000
  19 -> 0x1158e460913d0000
  20 -> 0x15af1d78b58c4000
  21 -> 0x1b1ae4d6e2ef5000
  22 -> 0x10f0cf064dd59200
  23 -> 0x152d02c7e14af680
  24 -> 0x1a784379d99db420
  25 -> 0x108b2a2c28029094
  26 -> 0x14adf4b7320334b9
  27 -> 0x19d971e4fe8401e7
  28 -> 0x1027e72f1f128130
  29 -> 0x1431e0fae6d7217c
  30 -> 0x193e5939a08ce9db
  31 -> 0x1f8def8808b02452
  32 -> 0x13b8b5b5056e16b3
  33 -> 0x18a6e32246c99c60
  34 -> 0x1ed09bead87c0378
  35 -> 0x13426172c74d822b
  36 -> 0x1812f9cf7920e2b6
  37 -> 0x1e17b84357691b64
  38 -> 0x12ced32a16a1b11e
  39 -> 0x178287f49c4a1d66
  40 -> 0x1d6329f1c35ca4bf
  41 -> 0x125dfa371a19e6f7
  42 -> 0x16f578c4e0a060b5
  43 -> 0x1cb2d6f618c878e3
  44 -> 0x11efc659cf7d4b8d
  45 -> 0x166bb7f0435c9e71
  _  -> 0x1c06a5ec5433c60d
#endif

-- | Take the high bits of m * 2^k / 5^q / 2^-e2+q+k
mulPow5InvDivPow2 :: Word32 -> Int -> Int -> Word32
mulPow5InvDivPow2 :: Word32 -> Int -> Int -> Word32
mulPow5InvDivPow2 Word32
m Int
q Int
j = Word32 -> Word64 -> Int -> Word32
mulShift32 Word32
m (Int -> Word64
get_float_pow5_inv_split Int
q) Int
j

-- | Take the high bits of m * 5^-e2-q / 2^k / 2^q-k
mulPow5DivPow2 :: Word32 -> Int -> Int -> Word32
mulPow5DivPow2 :: Word32 -> Int -> Int -> Word32
mulPow5DivPow2 Word32
m Int
i Int
j = Word32 -> Word64 -> Int -> Word32
mulShift32 Word32
m (Int -> Word64
get_float_pow5_split Int
i) Int
j

-- | Handle case e2 >= 0
f2dGT :: Int32 -> Word32 -> Word32 -> Word32 -> (BoundsState Word32, Int32)
f2dGT :: Int32 -> Word32 -> Word32 -> Word32 -> (BoundsState Word32, Int32)
f2dGT Int32
e2' Word32
u Word32
v Word32
w =
  let e2 :: Int
e2 = Int32 -> Int
int32ToInt Int32
e2'
      -- q = e10 = log_10(2^e2)
      q :: Int
q = Int -> Int
log10pow2 Int
e2
      -- k = B0 + log_2(5^q)
      k :: Int
k = Int
float_pow5_inv_bitcount Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int
pow5bits Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
      i :: Int
i = -Int
e2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
k
      -- (u, v, w) * 2^k / 5^q / 2^-e2+q+k
      u' :: Word32
u' = Word32 -> Int -> Int -> Word32
mulPow5InvDivPow2 Word32
u Int
q Int
i
      v' :: Word32
v' = Word32 -> Int -> Int -> Word32
mulPow5InvDivPow2 Word32
v Int
q Int
i
      w' :: Word32
w' = Word32 -> Int -> Int -> Word32
mulPow5InvDivPow2 Word32
w Int
q Int
i
      !lastRemoved :: Word32
lastRemoved =
        if Int
q Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 Bool -> Bool -> Bool
&& Word32 -> Word32
fquot10 (Word32
w' Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
1) Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word32 -> Word32
fquot10 Word32
u'
          -- We need to know one removed digit even if we are not going to loop
          -- below. We could use q = X - 1 above, except that would require 33
          -- bits for the result, and we've found that 32-bit arithmetic is
          -- faster even on 64-bit machines.
          then let l :: Int
l = Int
float_pow5_inv_bitcount Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int
pow5bits (Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
                in Word32 -> Word32
frem10 (Word32 -> Int -> Int -> Word32
mulPow5InvDivPow2 Word32
v (Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (-Int
e2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
l))
          else Word32
0
      !(Bool
vvTrailing, Bool
vuTrailing, Word32
vw') =
        case () of
          ()
_ | Int
q Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
9 Bool -> Bool -> Bool
&& Word32 -> Word32
frem5 Word32
v Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
0
                -> (Word32 -> Int -> Bool
forall a. Mantissa a => a -> Int -> Bool
multipleOfPowerOf5 Word32
v Int
q, Bool
False, Word32
w')
            | Int
q Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
9 Bool -> Bool -> Bool
&& Word32 -> Bool
forall a. Mantissa a => a -> Bool
acceptBounds Word32
v
                -> (Bool
False, Word32 -> Int -> Bool
forall a. Mantissa a => a -> Int -> Bool
multipleOfPowerOf5 Word32
u Int
q, Word32
w')
            | Int
q Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
9
                -> (Bool
False, Bool
False, Word32
w' Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Bool -> Word32
boolToWord32 (Word32 -> Int -> Bool
forall a. Mantissa a => a -> Int -> Bool
multipleOfPowerOf5 Word32
w Int
q))
            | Bool
otherwise
                -> (Bool
False, Bool
False, Word32
w')
   in (Word32
-> Word32 -> Word32 -> Word32 -> Bool -> Bool -> BoundsState Word32
forall a. a -> a -> a -> a -> Bool -> Bool -> BoundsState a
BoundsState Word32
u' Word32
v' Word32
vw' Word32
lastRemoved Bool
vuTrailing Bool
vvTrailing, Int -> Int32
intToInt32 Int
q)

-- | Handle case e2 < 0
f2dLT :: Int32 -> Word32 -> Word32 -> Word32 -> (BoundsState Word32, Int32)
f2dLT :: Int32 -> Word32 -> Word32 -> Word32 -> (BoundsState Word32, Int32)
f2dLT Int32
e2' Word32
u Word32
v Word32
w =
  let e2 :: Int
e2 = Int32 -> Int
int32ToInt Int32
e2'
      q :: Int
q = Int -> Int
log10pow5 (-Int
e2)
      e10 :: Int
e10 = Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
e2
      i :: Int
i = (-Int
e2) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
q
      -- k = log_2(5^-e2-q) - B1
      k :: Int
k = Int -> Int
pow5bits Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
float_pow5_bitcount
      j :: Int
j = Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k
      -- (u, v, w) * 5^-e2-q / 2^k / 2^q-k
      u' :: Word32
u' = Word32 -> Int -> Int -> Word32
mulPow5DivPow2 Word32
u Int
i Int
j
      v' :: Word32
v' = Word32 -> Int -> Int -> Word32
mulPow5DivPow2 Word32
v Int
i Int
j
      w' :: Word32
w' = Word32 -> Int -> Int -> Word32
mulPow5DivPow2 Word32
w Int
i Int
j
      !lastRemoved :: Word32
lastRemoved =
        if Int
q Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 Bool -> Bool -> Bool
&& Word32 -> Word32
fquot10 (Word32
w' Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
1) Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word32 -> Word32
fquot10 Word32
u'
          then let j' :: Int
j' = Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int -> Int
pow5bits (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
float_pow5_bitcount)
                in Word32 -> Word32
frem10 (Word32 -> Int -> Int -> Word32
mulPow5DivPow2 Word32
v (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int
j')
          else Word32
0
      !(Bool
vvTrailing , Bool
vuTrailing, Word32
vw') =
        case () of
          ()
_ | Int
q Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1 Bool -> Bool -> Bool
&& Word32 -> Bool
forall a. Mantissa a => a -> Bool
acceptBounds Word32
v
                -> (Bool
True, Word32
v Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
u Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
2, Word32
w') -- mmShift == 1
            | Int
q Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1
                -> (Bool
True, Bool
False, Word32
w' Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
1)
            | Int
q Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
31
                -> (Word32 -> Int -> Bool
forall a. Mantissa a => a -> Int -> Bool
multipleOfPowerOf2 Word32
v (Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1), Bool
False, Word32
w')
            | Bool
otherwise
                -> (Bool
False, Bool
False, Word32
w')
   in (Word32
-> Word32 -> Word32 -> Word32 -> Bool -> Bool -> BoundsState Word32
forall a. a -> a -> a -> a -> Bool -> Bool -> BoundsState a
BoundsState Word32
u' Word32
v' Word32
vw' Word32
lastRemoved Bool
vuTrailing Bool
vvTrailing, Int -> Int32
intToInt32 Int
e10)

-- | Returns the decimal representation of the given mantissa and exponent of a
-- 32-bit Float using the ryu algorithm.
f2d :: Word32 -> Word32 -> FloatingDecimal
f2d :: Word32 -> Word32 -> FloatingDecimal
f2d Word32
m Word32
e =
  let !mf :: Word32
mf = if Word32
e Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
0
              then Word32
m
              else (Word32
1 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
float_mantissa_bits) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word32
m
      !ef :: Int32
ef = Int -> Int32
intToInt32 (Int -> Int32) -> Int -> Int32
forall a b. (a -> b) -> a -> b
$ if Word32
e Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
0
              then Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int
float_bias Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
float_mantissa_bits)
              else Word32 -> Int
word32ToInt Word32
e Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int
float_bias Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
float_mantissa_bits)
      !e2 :: Int32
e2 = Int32
ef Int32 -> Int32 -> Int32
forall a. Num a => a -> a -> a
- Int32
2
      -- Step 2. 3-tuple (u, v, w) * 2**e2
      !u :: Word32
u = Word32
4 Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Word32
mf Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
1 Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Bool -> Word32
boolToWord32 (Word32
m Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word32
0 Bool -> Bool -> Bool
|| Word32
e Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word32
1)
      !v :: Word32
v = Word32
4 Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Word32
mf
      !w :: Word32
w = Word32
4 Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Word32
mf Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32
2
      -- Step 3. convert to decimal power base
      !(BoundsState Word32
state, Int32
e10) =
        if Int32
e2 Int32 -> Int32 -> Bool
forall a. Ord a => a -> a -> Bool
>= Int32
0
           then Int32 -> Word32 -> Word32 -> Word32 -> (BoundsState Word32, Int32)
f2dGT Int32
e2 Word32
u Word32
v Word32
w
           else Int32 -> Word32 -> Word32 -> Word32 -> (BoundsState Word32, Int32)
f2dLT Int32
e2 Word32
u Word32
v Word32
w
      -- Step 4: Find the shortest decimal representation in the interval of
      -- valid representations.
      !(Word32
output, Int32
removed) =
        let rounded :: BoundsState Word32 -> Word32
rounded = Bool -> BoundsState Word32 -> Word32
forall a. Mantissa a => Bool -> BoundsState a -> a
closestCorrectlyRounded (Word32 -> Bool
forall a. Mantissa a => a -> Bool
acceptBounds Word32
v)
         in (BoundsState Word32 -> Word32)
-> (BoundsState Word32, Int32) -> (Word32, Int32)
forall b c d. (b -> c) -> (b, d) -> (c, d)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first BoundsState Word32 -> Word32
rounded ((BoundsState Word32, Int32) -> (Word32, Int32))
-> (BoundsState Word32, Int32) -> (Word32, Int32)
forall a b. (a -> b) -> a -> b
$ if BoundsState Word32 -> Bool
forall a. BoundsState a -> Bool
vvIsTrailingZeros BoundsState Word32
state Bool -> Bool -> Bool
|| BoundsState Word32 -> Bool
forall a. BoundsState a -> Bool
vuIsTrailingZeros BoundsState Word32
state
           then BoundsState Word32 -> (BoundsState Word32, Int32)
forall a.
(Show a, Mantissa a) =>
BoundsState a -> (BoundsState a, Int32)
trimTrailing BoundsState Word32
state
           else BoundsState Word32 -> (BoundsState Word32, Int32)
forall a. Mantissa a => BoundsState a -> (BoundsState a, Int32)
trimNoTrailing BoundsState Word32
state
      !e' :: Int32
e' = Int32
e10 Int32 -> Int32 -> Int32
forall a. Num a => a -> a -> a
+ Int32
removed
   in Word32 -> Int32 -> FloatingDecimal
FloatingDecimal Word32
output Int32
e'

-- | Split a Float into (sign, mantissa, exponent)
breakdown :: Float -> (Bool, Word32, Word32)
breakdown :: Float -> (Bool, Word32, Word32)
breakdown Float
f =
  let bits :: Word32
bits = Float -> Word32
castFloatToWord32 Float
f
      sign :: Bool
sign = ((Word32
bits Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftR` (Int
float_mantissa_bits Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
float_exponent_bits)) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
1) Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word32
0
      mantissa :: Word32
mantissa = Word32
bits Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Int -> Word32
forall a. (Bits a, Integral a) => Int -> a
mask Int
float_mantissa_bits
      expo :: Word32
expo = (Word32
bits Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
float_mantissa_bits) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Int -> Word32
forall a. (Bits a, Integral a) => Int -> a
mask Int
float_exponent_bits
   in (Bool
sign, Word32
mantissa, Word32
expo)

-- | Dispatches to `f2d` and applies the given formatters
{-# INLINE f2s' #-}
f2s' :: (Bool -> Word32 -> Int32 -> a) -> (NonNumbersAndZero -> a) -> Float -> a
f2s' :: forall a.
(Bool -> Word32 -> Int32 -> a)
-> (NonNumbersAndZero -> a) -> Float -> a
f2s' Bool -> Word32 -> Int32 -> a
formatter NonNumbersAndZero -> a
specialFormatter Float
f =
  let (Bool
sign, Word32
mantissa, Word32
expo) = Float -> (Bool, Word32, Word32)
breakdown Float
f
   in if (Word32
expo Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> Word32
forall a. (Bits a, Integral a) => Int -> a
mask Int
float_exponent_bits) Bool -> Bool -> Bool
|| (Word32
expo Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
0 Bool -> Bool -> Bool
&& Word32
mantissa Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
0)
         then NonNumbersAndZero -> a
specialFormatter NonNumbersAndZero
                  { negative :: Bool
negative=Bool
sign
                  , exponent_all_one :: Bool
exponent_all_one=Word32
expo Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
> Word32
0
                  , mantissa_non_zero :: Bool
mantissa_non_zero=Word32
mantissa Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
> Word32
0 }
         else let FloatingDecimal Word32
m Int32
e = Word32 -> Word32 -> FloatingDecimal
f2d Word32
mantissa Word32
expo
               in Bool -> Word32 -> Int32 -> a
formatter Bool
sign Word32
m Int32
e

-- | Render a Float in scientific notation
f2s :: Float -> Builder
f2s :: Float -> Builder
f2s Float
f = BoundedPrim () -> () -> Builder
forall a. BoundedPrim a -> a -> Builder
primBounded ((Bool -> Word32 -> Int32 -> BoundedPrim ())
-> (NonNumbersAndZero -> BoundedPrim ()) -> Float -> BoundedPrim ()
forall a.
(Bool -> Word32 -> Int32 -> a)
-> (NonNumbersAndZero -> a) -> Float -> a
f2s' Bool -> Word32 -> Int32 -> BoundedPrim ()
forall a. Mantissa a => Bool -> a -> Int32 -> BoundedPrim ()
toCharsScientific NonNumbersAndZero -> BoundedPrim ()
toCharsNonNumbersAndZero Float
f) ()

-- | Returns the decimal representation of a Float. NaN and Infinity will
-- return `FloatingDecimal 0 0`
f2Intermediate :: Float -> FloatingDecimal
f2Intermediate :: Float -> FloatingDecimal
f2Intermediate = (Bool -> Word32 -> Int32 -> FloatingDecimal)
-> (NonNumbersAndZero -> FloatingDecimal)
-> Float
-> FloatingDecimal
forall a.
(Bool -> Word32 -> Int32 -> a)
-> (NonNumbersAndZero -> a) -> Float -> a
f2s' ((Word32 -> Int32 -> FloatingDecimal)
-> Bool -> Word32 -> Int32 -> FloatingDecimal
forall a b. a -> b -> a
const Word32 -> Int32 -> FloatingDecimal
FloatingDecimal) (FloatingDecimal -> NonNumbersAndZero -> FloatingDecimal
forall a b. a -> b -> a
const (FloatingDecimal -> NonNumbersAndZero -> FloatingDecimal)
-> FloatingDecimal -> NonNumbersAndZero -> FloatingDecimal
forall a b. (a -> b) -> a -> b
$ Word32 -> Int32 -> FloatingDecimal
FloatingDecimal Word32
0 Int32
0)