{-# 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 :: 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 = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int, Integer) -> Int
forall a b. (a, b) -> a
fst (Integer -> Integer -> (Int, Integer)
forall t a. (Integral t, Num a) => t -> t -> (a, t)
ilog Integer
b0 Integer
n0)
where
ilog :: t -> t -> (a, t)
ilog !t
b !t
n
| t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
b = (a
0, t
n)
| t
r t -> t -> Bool
forall a. Ord a => a -> a -> Bool
< t
b = ((,) (a -> t -> (a, t)) -> a -> t -> (a, t)
forall a b. (a -> b) -> a -> b
$! a
2a -> a -> a
forall a. Num a => a -> a -> a
*a
e) t
r
| Bool
otherwise = ((,) (a -> t -> (a, t)) -> a -> t -> (a, t)
forall a b. (a -> b) -> a -> b
$! a
2a -> a -> a
forall a. Num a => a -> a -> a
*a
ea -> a -> a
forall a. Num a => a -> a -> a
+a
1) (t -> (a, t)) -> t -> (a, t)
forall a b. (a -> b) -> a -> b
$! (t
r t -> t -> t
forall a. Integral a => a -> a -> a
`quot` t
b)
where
(a
e, t
r) = t -> t -> (a, t)
ilog (t
bt -> t -> t
forall a. Num a => a -> a -> a
*t
b) t
n
numTwoPowerDigits :: (Integral a, Bits a) => Int -> a -> Int
{-# INLINE numTwoPowerDigits #-}
numTwoPowerDigits :: 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 p. (Ord t, Num t, Num p, Bits t) => p -> t -> p
go Int
0 a
n0
where
go :: p -> t -> p
go !p
d !t
n
| t
n t -> t -> Bool
forall a. Ord a => a -> a -> Bool
> t
0 = p -> t -> p
go (p
dp -> p -> p
forall a. Num a => a -> a -> a
+p
1) (t
n t -> Int -> t
forall a. Bits a => a -> Int -> a
`shiftR` Int
p)
| Bool
otherwise = p
d
numDecimalDigits :: (Integral a) => a -> Int
{-# INLINE numDecimalDigits #-}
numDecimalDigits :: 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 -> p
fin a
n a
bound = if a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
bound then p
1 else p
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 p. (Ord a, Num p) => a -> a -> p
fin t
n t
100000
else t
6 t -> t -> t
forall a. Num a => a -> a -> a
+ t -> t -> t
forall a p. (Ord a, Num p) => a -> a -> p
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 p. (Ord a, Num p) => a -> a -> p
fin t
n t
1000000000
else t
10 t -> t -> t
forall a. Num a => a -> a -> a
+ t -> t -> t
forall a p. (Ord a, Num p) => a -> a -> p
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 #-}