{-# OPTIONS_GHC -Wall -fwarn-tabs #-}
{-# LANGUAGE BangPatterns #-}
module Data.ByteString.Lex.Internal
(
isNotPeriod
, isNotE
, isDecimal
, isDecimalZero
, toDigit
, addDigit
, numDigits
, numTwoPowerDigits
, numDecimalDigits
) where
import Data.Word (Word8, Word64)
import Data.Bits (Bits(shiftR))
{-# INLINE isNotPeriod #-}
isNotPeriod :: Word8 -> Bool
isNotPeriod :: Word8 -> Bool
isNotPeriod Word8
w = Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
0x2E
{-# INLINE isNotE #-}
isNotE :: Word8 -> Bool
isNotE :: Word8 -> Bool
isNotE Word8
w = Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
0x65 Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
0x45
{-# INLINE isDecimal #-}
isDecimal :: Word8 -> Bool
isDecimal :: Word8 -> Bool
isDecimal Word8
w = Word8
0x39 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
w Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0x30
{-# INLINE isDecimalZero #-}
isDecimalZero :: Word8 -> Bool
isDecimalZero :: Word8 -> Bool
isDecimalZero Word8
w = Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x30
{-# INLINE toDigit #-}
toDigit :: (Integral a) => Word8 -> a
toDigit :: forall a. Integral a => Word8 -> a
toDigit Word8
w = Word8 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
0x30)
{-# INLINE addDigit #-}
addDigit :: Int -> Word8 -> Int
addDigit :: Int -> Word8 -> Int
addDigit Int
n Word8
w = Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Word8 -> Int
forall a. Integral a => Word8 -> a
toDigit Word8
w
numDigits :: Integer -> Integer -> Int
{-# INLINE numDigits #-}
numDigits :: Integer -> Integer -> Int
numDigits !Integer
b0 !Integer
n0
| Integer
b0 Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
1 = [Char] -> Int
forall a. HasCallStack => [Char] -> a
error ([Char]
_numDigits [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
_nonpositiveBase)
| Integer
n0 Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 = [Char] -> Int
forall a. HasCallStack => [Char] -> a
error ([Char]
_numDigits [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
_negativeNumber)
| Bool
otherwise = ND -> Int
finish (Integer -> Integer -> ND
ilog Integer
b0 Integer
n0)
where
finish :: ND -> Int
finish (ND Int
e Integer
_) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
e
ilog :: Integer -> Integer -> ND
ilog !Integer
b !Integer
n
| Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
b = Int -> Integer -> ND
ND Int
0 Integer
n
| Integer
r Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
b = Int -> Integer -> ND
ND (Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
e) Integer
r
| Bool
otherwise = Int -> Integer -> ND
ND (Int
2Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
eInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Integer
r Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`quot` Integer
b)
where
ND Int
e Integer
r = Integer -> Integer -> ND
ilog (Integer
bInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
b) Integer
n
data ND = ND {-#UNPACK#-}!Int !Integer
numTwoPowerDigits :: (Integral a, Bits a) => Int -> a -> Int
{-# INLINE numTwoPowerDigits #-}
numTwoPowerDigits :: forall a. (Integral a, Bits a) => Int -> a -> Int
numTwoPowerDigits !Int
p !a
n0
| Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = [Char] -> Int
forall a. HasCallStack => [Char] -> a
error ([Char]
_numTwoPowerDigits [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
_nonpositiveBase)
| a
n0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = [Char] -> Int
forall a. HasCallStack => [Char] -> a
error ([Char]
_numTwoPowerDigits [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
_negativeNumber)
| a
n0 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Int
1
| Bool
otherwise = Int -> a -> Int
forall {t} {t}. (Ord t, Num t, Num t, Bits t) => t -> t -> t
go Int
0 a
n0
where
go :: t -> t -> t
go !t
d !t
n
| t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
> t
0 = t -> t -> t
go (t
dt -> t -> t
forall a. Num a => a -> a -> a
+t
1) (t
n t -> Int -> t
forall a. Bits a => a -> Int -> a
`shiftR` Int
p)
| Bool
otherwise = t
d
numDecimalDigits :: (Integral a) => a -> Int
{-# INLINE numDecimalDigits #-}
numDecimalDigits :: forall a. Integral a => a -> Int
numDecimalDigits a
n0
| a
n0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 = [Char] -> Int
forall a. HasCallStack => [Char] -> a
error ([Char]
_numDecimalDigits [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
_negativeNumber)
| a
n0 a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
limit = Integer -> Integer -> Int
numDigits Integer
10 (a -> Integer
forall a. Integral a => a -> Integer
toInteger a
n0)
| Bool
otherwise = Int -> Word64 -> Int
forall {t} {t}. (Num t, Integral t) => t -> t -> t
go Int
1 (a -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n0 :: Word64)
where
limit :: a
limit = Word64 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64
forall a. Bounded a => a
maxBound :: Word64)
fin :: a -> a -> a
fin a
n a
bound = if a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
bound then a
1 else a
0
go :: t -> t -> t
go !t
k !t
n
| t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
10 = t
k
| t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
100 = t
k t -> t -> t
forall a. Num a => a -> a -> a
+ t
1
| t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
1000 = t
k t -> t -> t
forall a. Num a => a -> a -> a
+ t
2
| t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
1000000000000 =
t
k t -> t -> t
forall a. Num a => a -> a -> a
+ if t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
100000000
then if t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
1000000
then if t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
10000
then t
3
else t
4 t -> t -> t
forall a. Num a => a -> a -> a
+ t -> t -> t
forall {a} {a}. (Ord a, Num a) => a -> a -> a
fin t
n t
100000
else t
6 t -> t -> t
forall a. Num a => a -> a -> a
+ t -> t -> t
forall {a} {a}. (Ord a, Num a) => a -> a -> a
fin t
n t
10000000
else if t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
10000000000
then t
8 t -> t -> t
forall a. Num a => a -> a -> a
+ t -> t -> t
forall {a} {a}. (Ord a, Num a) => a -> a -> a
fin t
n t
1000000000
else t
10 t -> t -> t
forall a. Num a => a -> a -> a
+ t -> t -> t
forall {a} {a}. (Ord a, Num a) => a -> a -> a
fin t
n t
100000000000
| Bool
otherwise = t -> t -> t
go (t
k t -> t -> t
forall a. Num a => a -> a -> a
+ t
12) (t
n t -> t -> t
forall a. Integral a => a -> a -> a
`quot` t
1000000000000)
_numDigits :: String
_numDigits :: [Char]
_numDigits = [Char]
"numDigits"
{-# NOINLINE _numDigits #-}
_numTwoPowerDigits :: String
_numTwoPowerDigits :: [Char]
_numTwoPowerDigits = [Char]
"numTwoPowerDigits"
{-# NOINLINE _numTwoPowerDigits #-}
_numDecimalDigits :: String
_numDecimalDigits :: [Char]
_numDecimalDigits = [Char]
"numDecimalDigits"
{-# NOINLINE _numDecimalDigits #-}
_nonpositiveBase :: String
_nonpositiveBase :: [Char]
_nonpositiveBase = [Char]
": base must be greater than one"
{-# NOINLINE _nonpositiveBase #-}
_negativeNumber :: String
_negativeNumber :: [Char]
_negativeNumber = [Char]
": number must be non-negative"
{-# NOINLINE _negativeNumber #-}