module Z.Data.Parser.Numeric
(
uint, int, integer
, uint_, int_, digit
, hex, hex', hex_
, rational
, float, double
, scientific
, scientifically
, rational'
, float', double'
, scientific'
, scientifically'
, w2iHex, w2iDec
, hexLoop
, decLoop
, decLoopIntegerFast
, sciToDouble
) where
import Control.Applicative
import Control.Monad
import Data.Bits
import Data.Int
import qualified Data.Scientific as Sci
import Data.Word
import GHC.Exts
import GHC.Num
import GHC.Float (expt)
import Z.Data.ASCII
import Z.Data.Parser.Base (Parser, (<?>))
import qualified Z.Data.Parser.Base as P
import qualified Z.Data.Vector.Base as V
import qualified Z.Data.Vector.Extra as V
import Z.Foreign
import System.IO.Unsafe
#define WORD64_SAFE_DIGITS_LEN 19
#define INT64_SAFE_DIGITS_LEN 18
hex :: forall a.(Integral a, FiniteBits a) => Parser a
{-# INLINABLE hex #-}
{-# SPECIALIZE INLINE hex :: Parser Int #-}
{-# SPECIALIZE INLINE hex :: Parser Int8 #-}
{-# SPECIALIZE INLINE hex :: Parser Int16 #-}
{-# SPECIALIZE INLINE hex :: Parser Int32 #-}
{-# SPECIALIZE INLINE hex :: Parser Int64 #-}
{-# SPECIALIZE INLINE hex :: Parser Word #-}
{-# SPECIALIZE INLINE hex :: Parser Word8 #-}
{-# SPECIALIZE INLINE hex :: Parser Word16 #-}
{-# SPECIALIZE INLINE hex :: Parser Word32 #-}
{-# SPECIALIZE INLINE hex :: Parser Word64 #-}
hex :: forall a. (Integral a, FiniteBits a) => Parser a
hex = Text
"Z.Data.Parser.Numeric.hex" forall a. Text -> Parser a -> Parser a
<?> do
Bytes
bs <- (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isHexDigit
if forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
bs forall a. Ord a => a -> a -> Bool
<= forall b. FiniteBits b => b -> Int
finiteBitSize (forall a. HasCallStack => a
undefined :: a) forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
2
then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a. (Integral a, Bits a) => a -> Bytes -> a
hexLoop a
0 Bytes
bs
else forall a. Text -> Parser a
P.fail' Text
"hex numeric number overflow"
hex' :: forall a.(Integral a, FiniteBits a) => Parser a
{-# INLINABLE hex' #-}
{-# SPECIALIZE INLINE hex' :: Parser Int #-}
{-# SPECIALIZE INLINE hex' :: Parser Int8 #-}
{-# SPECIALIZE INLINE hex' :: Parser Int16 #-}
{-# SPECIALIZE INLINE hex' :: Parser Int32 #-}
{-# SPECIALIZE INLINE hex' :: Parser Int64 #-}
{-# SPECIALIZE INLINE hex' :: Parser Word #-}
{-# SPECIALIZE INLINE hex' :: Parser Word8 #-}
{-# SPECIALIZE INLINE hex' :: Parser Word16 #-}
{-# SPECIALIZE INLINE hex' :: Parser Word32 #-}
{-# SPECIALIZE INLINE hex' :: Parser Word64 #-}
hex' :: forall a. (Integral a, FiniteBits a) => Parser a
hex' = Text
"Z.Data.Parser.Numeric.hex'" forall a. Text -> Parser a -> Parser a
<?> do
forall a. (Integral a, Bits a) => a -> Bytes -> a
hexLoop a
0 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
(Word8 -> Bool) -> Int -> Parser Bytes
P.takeN Word8 -> Bool
isHexDigit (forall b. FiniteBits b => b -> Int
finiteBitSize (forall a. HasCallStack => a
undefined :: a) forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
2)
where
hex_ :: (Integral a, Bits a) => Parser a
{-# INLINABLE hex_ #-}
{-# SPECIALIZE INLINE hex_ :: Parser Int #-}
{-# SPECIALIZE INLINE hex_ :: Parser Int8 #-}
{-# SPECIALIZE INLINE hex_ :: Parser Int16 #-}
{-# SPECIALIZE INLINE hex_ :: Parser Int32 #-}
{-# SPECIALIZE INLINE hex_ :: Parser Int64 #-}
{-# SPECIALIZE INLINE hex_ :: Parser Word #-}
{-# SPECIALIZE INLINE hex_ :: Parser Word8 #-}
{-# SPECIALIZE INLINE hex_ :: Parser Word16 #-}
{-# SPECIALIZE INLINE hex_ :: Parser Word32 #-}
{-# SPECIALIZE INLINE hex_ :: Parser Word64 #-}
hex_ :: forall a. (Integral a, Bits a) => Parser a
hex_ = Text
"Z.Data.Parser.Numeric.hex_" forall a. Text -> Parser a -> Parser a
<?> forall a. (Integral a, Bits a) => a -> Bytes -> a
hexLoop a
0 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isHexDigit
hexLoop :: forall a. (Integral a, Bits a)
=> a
-> V.Bytes
-> a
{-# INLINE hexLoop #-}
hexLoop :: forall a. (Integral a, Bits a) => a -> Bytes -> a
hexLoop = forall (v :: * -> *) a b. Vec v a => (b -> a -> b) -> b -> v a -> b
V.foldl' a -> Word8 -> a
step
where
step :: a -> Word8 -> a
step a
a Word8
w = a
a forall a. Bits a => a -> Int -> a
`unsafeShiftL` Int
4 forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Integral a => Word8 -> a
w2iHex Word8
w :: a)
w2iHex :: Integral a => Word8 -> a
{-# INLINE w2iHex #-}
w2iHex :: forall a. Integral a => Word8 -> a
w2iHex Word8
w
| Word8
w forall a. Ord a => a -> a -> Bool
<= Word8
57 = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w forall a. Num a => a -> a -> a
- a
48
| Word8
w forall a. Ord a => a -> a -> Bool
<= Word8
70 = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w forall a. Num a => a -> a -> a
- a
55
| Bool
otherwise = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w forall a. Num a => a -> a -> a
- a
87
uint_ :: forall a. (Integral a, Bounded a) => Parser a
{-# INLINABLE uint_ #-}
{-# SPECIALIZE INLINE uint_ :: Parser Int #-}
{-# SPECIALIZE INLINE uint_ :: Parser Int8 #-}
{-# SPECIALIZE INLINE uint_ :: Parser Int16 #-}
{-# SPECIALIZE INLINE uint_ :: Parser Int32 #-}
{-# SPECIALIZE INLINE uint_ :: Parser Int64 #-}
{-# SPECIALIZE INLINE uint_ :: Parser Word #-}
{-# SPECIALIZE INLINE uint_ :: Parser Word8 #-}
{-# SPECIALIZE INLINE uint_ :: Parser Word16 #-}
{-# SPECIALIZE INLINE uint_ :: Parser Word32 #-}
{-# SPECIALIZE INLINE uint_ :: Parser Word64 #-}
uint_ :: forall a. (Integral a, Bounded a) => Parser a
uint_ = Text
"Z.Data.Parser.Numeric.uint_" forall a. Text -> Parser a -> Parser a
<?> forall a. Integral a => a -> Bytes -> a
decLoop a
0 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isDigit
uint :: forall a. (Integral a, Bounded a) => Parser a
{-# INLINABLE uint #-}
{-# SPECIALIZE INLINE uint :: Parser Int #-}
{-# SPECIALIZE INLINE uint :: Parser Int8 #-}
{-# SPECIALIZE INLINE uint :: Parser Int16 #-}
{-# SPECIALIZE INLINE uint :: Parser Int32 #-}
{-# SPECIALIZE INLINE uint :: Parser Int64 #-}
{-# SPECIALIZE INLINE uint :: Parser Word #-}
{-# SPECIALIZE INLINE uint :: Parser Word8 #-}
{-# SPECIALIZE INLINE uint :: Parser Word16 #-}
{-# SPECIALIZE INLINE uint :: Parser Word32 #-}
{-# SPECIALIZE INLINE uint :: Parser Word64 #-}
uint :: forall a. (Integral a, Bounded a) => Parser a
uint = Text
"Z.Data.Parser.Numeric.uint" forall a. Text -> Parser a -> Parser a
<?> do
Bytes
bs <- (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isDigit
if forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
bs forall a. Ord a => a -> a -> Bool
<= WORD64_SAFE_DIGITS_LEN
then do
let w64 :: Word64
w64 = forall a. Integral a => a -> Bytes -> a
decLoop @Word64 Word64
0 Bytes
bs
if Word64
w64 forall a. Ord a => a -> a -> Bool
<= forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound :: a)
then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
w64
else forall a. Text -> Parser a
P.fail' Text
"decimal numeric value overflow"
else do
let w64 :: Integer
w64 = forall a. Integral a => a -> Bytes -> a
decLoop @Integer Integer
0 Bytes
bs
if Integer
w64 forall a. Ord a => a -> a -> Bool
<= forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound :: a)
then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
w64
else forall a. Text -> Parser a
P.fail' Text
"decimal numeric value overflow"
decLoop :: Integral a
=> a
-> V.Bytes
-> a
{-# INLINE decLoop #-}
decLoop :: forall a. Integral a => a -> Bytes -> a
decLoop = forall (v :: * -> *) a b. Vec v a => (b -> a -> b) -> b -> v a -> b
V.foldl' forall {a}. Integral a => a -> Word8 -> a
step
where step :: a -> Word8 -> a
step a
a Word8
w = a
a forall a. Num a => a -> a -> a
* a
10 forall a. Num a => a -> a -> a
+ forall a. Integral a => Word8 -> a
w2iDec Word8
w
w2iDec :: Integral a => Word8 -> a
{-# INLINE w2iDec #-}
w2iDec :: forall a. Integral a => Word8 -> a
w2iDec Word8
w = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w forall a. Num a => a -> a -> a
- a
48
decLoopIntegerFast :: V.Bytes -> Integer
{-# INLINE decLoopIntegerFast #-}
decLoopIntegerFast :: Bytes -> Integer
decLoopIntegerFast Bytes
bs
| forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
bs forall a. Ord a => a -> a -> Bool
<= WORD64_SAFE_DIGITS_LEN = fromIntegral (decLoop @Word64 0 bs)
| Bool
otherwise = forall a. Integral a => a -> Bytes -> a
decLoop @Integer Integer
0 Bytes
bs
digit :: Parser Int
{-# INLINE digit #-}
digit :: Parser Int
digit = do
Word8
d <- (Word8 -> Bool) -> Parser Word8
P.satisfy Word8 -> Bool
isDigit
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a. Integral a => Word8 -> a
w2iDec Word8
d
int :: forall a. (Integral a, Bounded a) => Parser a
{-# INLINABLE int #-}
{-# SPECIALIZE INLINE int :: Parser Int #-}
{-# SPECIALIZE INLINE int :: Parser Int8 #-}
{-# SPECIALIZE INLINE int :: Parser Int16 #-}
{-# SPECIALIZE INLINE int :: Parser Int32 #-}
{-# SPECIALIZE INLINE int :: Parser Int64 #-}
{-# SPECIALIZE INLINE int :: Parser Word #-}
{-# SPECIALIZE INLINE int :: Parser Word8 #-}
{-# SPECIALIZE INLINE int :: Parser Word16 #-}
{-# SPECIALIZE INLINE int :: Parser Word32 #-}
{-# SPECIALIZE INLINE int :: Parser Word64 #-}
int :: forall a. (Integral a, Bounded a) => Parser a
int = Text
"Z.Data.Parser.Numeric.int" forall a. Text -> Parser a -> Parser a
<?> do
Word8
w <- Parser Word8
P.peek
if Word8
w forall a. Eq a => a -> a -> Bool
== Word8
MINUS
then Parser ()
P.skipWord8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser a
loopNe
else if Word8
w forall a. Eq a => a -> a -> Bool
== Word8
PLUS then Parser ()
P.skipWord8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser a
loop else Parser a
loop
where
loop :: Parser a
loop = do
Bytes
bs <- (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isDigit
if forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
bs forall a. Ord a => a -> a -> Bool
<= WORD64_SAFE_DIGITS_LEN
then do
let w64 :: Word64
w64 = forall a. Integral a => a -> Bytes -> a
decLoop @Word64 Word64
0 Bytes
bs
if Word64
w64 forall a. Ord a => a -> a -> Bool
<= forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound :: a)
then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
w64
else forall a. Text -> Parser a
P.fail' Text
"decimal numeric value overflow"
else do
let w64 :: Integer
w64 = forall a. Integral a => a -> Bytes -> a
decLoop @Integer Integer
0 Bytes
bs
if Integer
w64 forall a. Ord a => a -> a -> Bool
<= forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound :: a)
then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
w64
else forall a. Text -> Parser a
P.fail' Text
"decimal numeric value overflow"
loopNe :: Parser a
loopNe = do
Bytes
bs <- (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isDigit
if forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
bs forall a. Ord a => a -> a -> Bool
<= INT64_SAFE_DIGITS_LEN
then do
let i64 :: Int64
i64 = forall a. Num a => a -> a
negate (forall a. Integral a => a -> Bytes -> a
decLoop @Int64 Int64
0 Bytes
bs)
if Int64
i64 forall a. Ord a => a -> a -> Bool
>= forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
minBound :: a)
then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
i64
else forall a. Text -> Parser a
P.fail' Text
"decimal numeric value overflow"
else do
let i64 :: Integer
i64 = forall a. Num a => a -> a
negate (forall a. Integral a => a -> Bytes -> a
decLoop @Integer Integer
0 Bytes
bs)
if Integer
i64 forall a. Ord a => a -> a -> Bool
>= forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
minBound :: a)
then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$! forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
i64
else forall a. Text -> Parser a
P.fail' Text
"decimal numeric value overflow"
int_ :: (Integral a, Bounded a) => Parser a
{-# INLINABLE int_ #-}
{-# SPECIALIZE INLINE int_ :: Parser Int #-}
{-# SPECIALIZE INLINE int_ :: Parser Int8 #-}
{-# SPECIALIZE INLINE int_ :: Parser Int16 #-}
{-# SPECIALIZE INLINE int_ :: Parser Int32 #-}
{-# SPECIALIZE INLINE int_ :: Parser Int64 #-}
{-# SPECIALIZE INLINE int_ :: Parser Word #-}
{-# SPECIALIZE INLINE int_ :: Parser Word8 #-}
{-# SPECIALIZE INLINE int_ :: Parser Word16 #-}
{-# SPECIALIZE INLINE int_ :: Parser Word32 #-}
{-# SPECIALIZE INLINE int_ :: Parser Word64 #-}
int_ :: forall a. (Integral a, Bounded a) => Parser a
int_ = Text
"Z.Data.Parser.Numeric.int_" forall a. Text -> Parser a -> Parser a
<?> do
Word8
w <- Parser Word8
P.peek
if Word8
w forall a. Eq a => a -> a -> Bool
== Word8
MINUS
then Parser ()
P.skipWord8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (forall a. Num a => a -> a
negate forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser a
loop)
else if Word8
w forall a. Eq a => a -> a -> Bool
== Word8
PLUS then Parser ()
P.skipWord8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser a
loop else Parser a
loop
where
loop :: Parser a
loop = forall a. Integral a => a -> Bytes -> a
decLoop a
0 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isDigit
integer :: Parser Integer
{-# INLINABLE integer #-}
integer :: Parser Integer
integer = Text
"Z.Data.Parser.Numeric.integer" forall a. Text -> Parser a -> Parser a
<?> do
Word8
w <- Parser Word8
P.peek
if Word8
w forall a. Eq a => a -> a -> Bool
== Word8
MINUS
then Parser ()
P.skipWord8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (forall a. Num a => a -> a
negate forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Integer
integer')
else if Word8
w forall a. Eq a => a -> a -> Bool
== Word8
PLUS then Parser ()
P.skipWord8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Integer
integer' else Parser Integer
integer'
where
integer' :: Parser Integer
integer' = Bytes -> Integer
decLoopIntegerFast forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isDigit
rational :: (Fractional a) => Parser a
{-# INLINABLE rational #-}
rational :: forall a. Fractional a => Parser a
rational = Text
"Z.Data.Parser.Numeric.rational" forall a. Text -> Parser a -> Parser a
<?> forall a. (Scientific -> a) -> Parser a
scientificallyInternal forall a b. (Real a, Fractional b) => a -> b
realToFrac
double :: Parser Double
{-# INLINABLE double #-}
double :: Parser Double
double = Text
"Z.Data.Parser.Numeric.double" forall a. Text -> Parser a -> Parser a
<?> forall a. (Scientific -> a) -> Parser a
scientificallyInternal Scientific -> Double
sciToDouble
float :: Parser Float
{-# INLINABLE float #-}
float :: Parser Float
float = Text
"Z.Data.Parser.Numeric.float" forall a. Text -> Parser a -> Parser a
<?> forall a. (Scientific -> a) -> Parser a
scientificallyInternal forall a. RealFloat a => Scientific -> a
Sci.toRealFloat
scientific :: Parser Sci.Scientific
{-# INLINABLE scientific #-}
scientific :: Parser Scientific
scientific = Text
"Z.Data.Parser.Numeric.scientific" forall a. Text -> Parser a -> Parser a
<?> forall a. (Scientific -> a) -> Parser a
scientificallyInternal forall a. a -> a
id
scientifically :: (Sci.Scientific -> a) -> Parser a
{-# INLINABLE scientifically #-}
scientifically :: forall a. (Scientific -> a) -> Parser a
scientifically Scientific -> a
h = Text
"Z.Data.Parser.Numeric.scientifically" forall a. Text -> Parser a -> Parser a
<?> forall a. (Scientific -> a) -> Parser a
scientificallyInternal Scientific -> a
h
scientificallyInternal :: (Sci.Scientific -> a) -> Parser a
{-# INLINE scientificallyInternal #-}
scientificallyInternal :: forall a. (Scientific -> a) -> Parser a
scientificallyInternal Scientific -> a
h = do
!Word8
sign <- Parser Word8
P.peek
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Word8
sign forall a. Eq a => a -> a -> Bool
== Word8
PLUS Bool -> Bool -> Bool
|| Word8
sign forall a. Eq a => a -> a -> Bool
== Word8
MINUS) (Parser ()
P.skipWord8)
!Bytes
intPart <- (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isDigit
!Scientific
sci <- (do
!Bytes
fracPart <- Word8 -> Parser ()
P.word8 Word8
DOT forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isDigit
let !ilen :: Int
ilen = forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
intPart
!flen :: Int
flen = forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
fracPart
!base :: Integer
base =
if Int
ilen forall a. Num a => a -> a -> a
+ Int
flen forall a. Ord a => a -> a -> Bool
<= WORD64_SAFE_DIGITS_LEN
then forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Integral a => a -> Bytes -> a
decLoop @Word64 (forall a. Integral a => a -> Bytes -> a
decLoop @Word64 Word64
0 Bytes
intPart) Bytes
fracPart)
else
let i :: Integer
i = Bytes -> Integer
decLoopIntegerFast Bytes
intPart
f :: Integer
f = Bytes -> Integer
decLoopIntegerFast Bytes
fracPart
in Integer
i forall a. Num a => a -> a -> a
* (Integer -> Int -> Integer
expt Integer
10 Int
flen) forall a. Num a => a -> a -> a
+ Integer
f
Integer -> Int -> Parser Scientific
parseE Integer
base Int
flen) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Integer -> Int -> Parser Scientific
parseE (Bytes -> Integer
decLoopIntegerFast Bytes
intPart) Int
0)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (if Word8
sign forall a. Eq a => a -> a -> Bool
/= Word8
MINUS then Scientific -> a
h Scientific
sci else Scientific -> a
h (forall a. Num a => a -> a
negate Scientific
sci))
where
parseE :: Integer -> Int -> Parser Scientific
parseE Integer
c Int
e =
(do Word8
_ <- (Word8 -> Bool) -> Parser Word8
P.satisfy (\Word8
w -> Word8
w forall a. Eq a => a -> a -> Bool
== Word8
LETTER_e Bool -> Bool -> Bool
|| Word8
w forall a. Eq a => a -> a -> Bool
== Word8
LETTER_E)
Int
e' <- forall a. (Integral a, Bounded a) => Parser a
int
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$! Integer -> Int -> Scientific
Sci.scientific Integer
c (Int
e' forall a. Num a => a -> a -> a
- Int
e)) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$! Integer -> Int -> Scientific
Sci.scientific Integer
c (forall a. Num a => a -> a
negate Int
e))
rational' :: (Fractional a) => Parser a
{-# INLINABLE rational' #-}
rational' :: forall a. Fractional a => Parser a
rational' = Text
"Z.Data.Parser.Numeric.rational'" forall a. Text -> Parser a -> Parser a
<?> forall a. (Scientific -> a) -> Parser a
scientificallyInternal' forall a b. (Real a, Fractional b) => a -> b
realToFrac
double' :: Parser Double
{-# INLINABLE double' #-}
double' :: Parser Double
double' = Text
"Z.Data.Parser.Numeric.double'" forall a. Text -> Parser a -> Parser a
<?> forall a. (Scientific -> a) -> Parser a
scientificallyInternal' Scientific -> Double
sciToDouble
#define FASTFLOAT_SMALLEST_POWER -325
#define FASTFLOAT_LARGEST_POWER 308
sciToDouble :: Sci.Scientific -> Double
{-# INLINABLE sciToDouble #-}
sciToDouble :: Scientific -> Double
sciToDouble Scientific
sci = case Integer
c of
(IS Int#
i#) | (Int
e forall a. Ord a => a -> a -> Bool
>= FASTFLOAT_SMALLEST_POWER && e <= FASTFLOAT_LARGEST_POWER) -> unsafeDupablePerformIO $ do
let i = (I# i#)
s = if i >= 0 then 0 else 1
i' = fromIntegral $ if i >= 0 then i else (0-i)
(success, r) <- allocPrimUnsafe @Word8 (compute_float_64 (fromIntegral e) i' s)
if success == 0
then return $! Sci.toRealFloat sci
else return $! r
Integer
_ -> forall a. RealFloat a => Scientific -> a
Sci.toRealFloat Scientific
sci
where
e :: Int
e = Scientific -> Int
Sci.base10Exponent Scientific
sci
c :: Integer
c = Scientific -> Integer
Sci.coefficient Scientific
sci
float' :: Parser Float
{-# INLINABLE float' #-}
float' :: Parser Float
float' = Text
"Z.Data.Parser.Numeric.float'" forall a. Text -> Parser a -> Parser a
<?> forall a. (Scientific -> a) -> Parser a
scientificallyInternal' forall a. RealFloat a => Scientific -> a
Sci.toRealFloat
scientific' :: Parser Sci.Scientific
{-# INLINABLE scientific' #-}
scientific' :: Parser Scientific
scientific' = Text
"Z.Data.Parser.Numeric.scientific'" forall a. Text -> Parser a -> Parser a
<?> forall a. (Scientific -> a) -> Parser a
scientificallyInternal' forall a. a -> a
id
scientifically' :: (Sci.Scientific -> a) -> P.Parser a
{-# INLINABLE scientifically' #-}
scientifically' :: forall a. (Scientific -> a) -> Parser a
scientifically' Scientific -> a
h = Text
"Z.Data.Parser.Numeric.scientifically'" forall a. Text -> Parser a -> Parser a
<?> forall a. (Scientific -> a) -> Parser a
scientificallyInternal' Scientific -> a
h
scientificallyInternal' :: (Sci.Scientific -> a) -> P.Parser a
{-# INLINE scientificallyInternal' #-}
scientificallyInternal' :: forall a. (Scientific -> a) -> Parser a
scientificallyInternal' Scientific -> a
h = do
!Word8
sign <- Parser Word8
P.peek
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Word8
sign forall a. Eq a => a -> a -> Bool
== Word8
MINUS) (Parser ()
P.skipWord8)
!Bytes
intPart <- (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isDigit
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
intPart forall a. Ord a => a -> a -> Bool
> Int
1 Bool -> Bool -> Bool
&& forall (v :: * -> *) a. (Vec v a, HasCallStack) => v a -> a
V.head Bytes
intPart forall a. Eq a => a -> a -> Bool
== Word8
DIGIT_0) (forall a. Text -> Parser a
P.fail' Text
"leading zeros are not allowed")
Maybe Word8
mdot <- Parser (Maybe Word8)
P.peekMaybe
!Scientific
sci <- case Maybe Word8
mdot of
Just Word8
DOT -> do
!Bytes
fracPart <- Parser ()
P.skipWord8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Word8 -> Bool) -> Parser Bytes
P.takeWhile1 Word8 -> Bool
isDigit
let !ilen :: Int
ilen = forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
intPart
!flen :: Int
flen = forall (v :: * -> *) a. Vec v a => v a -> Int
V.length Bytes
fracPart
!base :: Integer
base =
if Int
ilen forall a. Num a => a -> a -> a
+ Int
flen forall a. Ord a => a -> a -> Bool
<= WORD64_SAFE_DIGITS_LEN
then forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Integral a => a -> Bytes -> a
decLoop @Word64 (forall a. Integral a => a -> Bytes -> a
decLoop @Word64 Word64
0 Bytes
intPart) Bytes
fracPart)
else
let i :: Integer
i = Bytes -> Integer
decLoopIntegerFast Bytes
intPart
f :: Integer
f = Bytes -> Integer
decLoopIntegerFast Bytes
fracPart
in Integer
i forall a. Num a => a -> a -> a
* (Integer -> Int -> Integer
expt Integer
10 Int
flen) forall a. Num a => a -> a -> a
+ Integer
f
Integer -> Int -> Parser Scientific
parseE Integer
base Int
flen
Maybe Word8
_ -> Integer -> Int -> Parser Scientific
parseE (Bytes -> Integer
decLoopIntegerFast Bytes
intPart) Int
0
forall (f :: * -> *) a. Applicative f => a -> f a
pure (if Word8
sign forall a. Eq a => a -> a -> Bool
/= Word8
MINUS then Scientific -> a
h Scientific
sci else Scientific -> a
h (forall a. Num a => a -> a
negate Scientific
sci))
where
parseE :: Integer -> Int -> Parser Scientific
parseE !Integer
c !Int
e = do
Maybe Word8
me <- Parser (Maybe Word8)
P.peekMaybe
Int
e' <- case Maybe Word8
me of
Just Word8
ec | Word8
ec forall a. Eq a => a -> a -> Bool
== Word8
LETTER_e Bool -> Bool -> Bool
|| Word8
ec forall a. Eq a => a -> a -> Bool
== Word8
LETTER_E -> Parser ()
P.skipWord8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall a. (Integral a, Bounded a) => Parser a
int
Maybe Word8
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
0
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$! Integer -> Int -> Scientific
Sci.scientific Integer
c (Int
e' forall a. Num a => a -> a -> a
- Int
e)
foreign import ccall unsafe compute_float_64 :: Int64
-> Word64
-> Word8
-> MBA# Word8
-> IO Double