{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -ddump-simpl -dsuppress-all -ddump-to-file #-}
module Data.Integer.Conversion (
textToInteger,
byteStringToInteger,
stringToInteger,
stringToIntegerWithLen,
) where
import Control.Monad.ST (ST, runST)
import Data.ByteString (ByteString)
import Data.Char (ord)
import Data.Primitive.Array (MutableArray, newArray, readArray, writeArray)
import Data.Text.Internal (Text (..))
import Data.Word (Word8)
import qualified Data.ByteString as BS
import qualified Data.List as L
import qualified Data.Text as T
textToInteger :: Text -> Integer
textToInteger :: Text -> Integer
textToInteger t :: Text
t@(Text Array
_arr Int
_off Int
len)
| Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
40 = Text -> Integer
complexTextToInteger Text
t
| Bool
otherwise = Text -> Integer
simpleTextToInteger Text
t
simpleTextToInteger :: Text -> Integer
simpleTextToInteger :: Text -> Integer
simpleTextToInteger = (Integer -> Char -> Integer) -> Integer -> Text -> Integer
forall a. (a -> Char -> a) -> a -> Text -> a
T.foldl' (\Integer
acc Char
c -> Integer
acc Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
10 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Char -> Integer
fromChar Char
c) Integer
0
complexTextToInteger :: Text -> Integer
complexTextToInteger :: Text -> Integer
complexTextToInteger t0 :: Text
t0@(Text Array
_ Int
_ Int
len) = (forall s. ST s Integer) -> Integer
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Integer) -> Integer)
-> (forall s. ST s Integer) -> Integer
forall a b. (a -> b) -> a -> b
$ do
MutableArray s Integer
arr <- Int -> Integer -> ST s (MutableArray (PrimState (ST s)) Integer)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (MutableArray (PrimState m) a)
newArray Int
len Integer
integer0
MutableArray s Integer -> Text -> Int -> ST s Integer
forall s. MutableArray s Integer -> Text -> Int -> ST s Integer
loop MutableArray s Integer
arr Text
t0 Int
0
where
loop :: MutableArray s Integer -> Text -> Int -> ST s Integer
loop :: forall s. MutableArray s Integer -> Text -> Int -> ST s Integer
loop !MutableArray s Integer
arr !Text
t !Int
o = case Text -> Maybe (Char, Text)
T.uncons Text
t of
Just (Char
c, Text
t') -> do
MutableArray (PrimState (ST s)) Integer
-> Int -> Integer -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> a -> m ()
writeArray MutableArray s Integer
MutableArray (PrimState (ST s)) Integer
arr Int
o (Integer -> ST s ()) -> Integer -> ST s ()
forall a b. (a -> b) -> a -> b
$! Char -> Integer
fromChar Char
c
MutableArray s Integer -> Text -> Int -> ST s Integer
forall s. MutableArray s Integer -> Text -> Int -> ST s Integer
loop MutableArray s Integer
arr Text
t' (Int
o Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
Maybe (Char, Text)
Nothing -> MutableArray s Integer -> Int -> Integer -> ST s Integer
forall s. MutableArray s Integer -> Int -> Integer -> ST s Integer
algorithm MutableArray s Integer
arr Int
o Integer
10
fromChar :: Char -> Integer
fromChar :: Char -> Integer
fromChar Char
c = Int -> Integer
forall a. Integral a => a -> Integer
toInteger (Char -> Int
ord Char
c Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
48 :: Int)
{-# INLINE fromChar #-}
byteStringToInteger :: ByteString -> Integer
byteStringToInteger :: ByteString -> Integer
byteStringToInteger ByteString
bs
| Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
40 = Int -> ByteString -> Integer
complexByteStringToInteger Int
len ByteString
bs
| Bool
otherwise = ByteString -> Integer
simpleByteStringToInteger ByteString
bs
where
!len :: Int
len = ByteString -> Int
BS.length ByteString
bs
simpleByteStringToInteger :: BS.ByteString -> Integer
simpleByteStringToInteger :: ByteString -> Integer
simpleByteStringToInteger = (Integer -> Word8 -> Integer) -> Integer -> ByteString -> Integer
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
BS.foldl' (\Integer
acc Word8
w -> Integer
acc Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
10 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Word8 -> Integer
fromWord8 Word8
w) Integer
0
complexByteStringToInteger :: Int -> BS.ByteString -> Integer
complexByteStringToInteger :: Int -> ByteString -> Integer
complexByteStringToInteger Int
len ByteString
bs = (forall s. ST s Integer) -> Integer
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Integer) -> Integer)
-> (forall s. ST s Integer) -> Integer
forall a b. (a -> b) -> a -> b
$ do
MutableArray s Integer
arr <- Int -> Integer -> ST s (MutableArray (PrimState (ST s)) Integer)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (MutableArray (PrimState m) a)
newArray Int
len' Integer
0
if Int -> Bool
forall a. Integral a => a -> Bool
even Int
len
then do
MutableArray s Integer -> Int -> Int -> ST s Integer
forall s. MutableArray s Integer -> Int -> Int -> ST s Integer
loop MutableArray s Integer
arr Int
0 Int
0
else do
MutableArray (PrimState (ST s)) Integer
-> Int -> Integer -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> a -> m ()
writeArray MutableArray s Integer
MutableArray (PrimState (ST s)) Integer
arr Int
0 (Integer -> ST s ()) -> Integer -> ST s ()
forall a b. (a -> b) -> a -> b
$! ByteString -> Int -> Integer
indexBS ByteString
bs Int
0
MutableArray s Integer -> Int -> Int -> ST s Integer
forall s. MutableArray s Integer -> Int -> Int -> ST s Integer
loop MutableArray s Integer
arr Int
1 Int
1
where
len' :: Int
len' = (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2
loop :: MutableArray s Integer -> Int -> Int -> ST s Integer
loop :: forall s. MutableArray s Integer -> Int -> Int -> ST s Integer
loop !MutableArray s Integer
arr !Int
i !Int
o | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = do
MutableArray (PrimState (ST s)) Integer
-> Int -> Integer -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> a -> m ()
writeArray MutableArray s Integer
MutableArray (PrimState (ST s)) Integer
arr Int
o (Integer -> ST s ()) -> Integer -> ST s ()
forall a b. (a -> b) -> a -> b
$! ByteString -> Int -> Integer
indexBS ByteString
bs Int
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
10 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ ByteString -> Int -> Integer
indexBS ByteString
bs (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
MutableArray s Integer -> Int -> Int -> ST s Integer
forall s. MutableArray s Integer -> Int -> Int -> ST s Integer
loop MutableArray s Integer
arr (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) (Int
o Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
loop MutableArray s Integer
arr Int
_ Int
_ = MutableArray s Integer -> Int -> Integer -> ST s Integer
forall s. MutableArray s Integer -> Int -> Integer -> ST s Integer
algorithm MutableArray s Integer
arr Int
len' Integer
100
indexBS :: BS.ByteString -> Int -> Integer
indexBS :: ByteString -> Int -> Integer
indexBS ByteString
bs Int
i = Word8 -> Integer
fromWord8 (HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bs Int
i)
{-# INLINE indexBS #-}
fromWord8 :: Word8 -> Integer
fromWord8 :: Word8 -> Integer
fromWord8 Word8
w = Int -> Integer
forall a. Integral a => a -> Integer
toInteger (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
48 :: Int)
{-# INLINE fromWord8 #-}
stringToInteger :: String -> Integer
stringToInteger :: String -> Integer
stringToInteger String
str = String -> Int -> Integer
stringToIntegerWithLen String
str (String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
str)
stringToIntegerWithLen :: String -> Int -> Integer
stringToIntegerWithLen :: String -> Int -> Integer
stringToIntegerWithLen String
str Int
len
| Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
40 = Int -> String -> Integer
complexStringToInteger Int
len String
str
| Bool
otherwise = String -> Integer
simpleStringToInteger String
str
simpleStringToInteger :: String -> Integer
simpleStringToInteger :: String -> Integer
simpleStringToInteger = (Integer -> Char -> Integer) -> Integer -> String -> Integer
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
L.foldl' Integer -> Char -> Integer
step Integer
0 where
step :: Integer -> Char -> Integer
step Integer
a Char
b = Integer
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
10 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Char -> Integer
fromChar Char
b
complexStringToInteger :: Int -> String -> Integer
complexStringToInteger :: Int -> String -> Integer
complexStringToInteger Int
len String
str = (forall s. ST s Integer) -> Integer
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Integer) -> Integer)
-> (forall s. ST s Integer) -> Integer
forall a b. (a -> b) -> a -> b
$ do
MutableArray s Integer
arr <- Int -> Integer -> ST s (MutableArray (PrimState (ST s)) Integer)
forall (m :: * -> *) a.
PrimMonad m =>
Int -> a -> m (MutableArray (PrimState m) a)
newArray Int
len' Integer
integer0
if Int -> Bool
forall a. Integral a => a -> Bool
even Int
len
then MutableArray s Integer -> String -> Int -> ST s Integer
forall s. MutableArray s Integer -> String -> Int -> ST s Integer
loop MutableArray s Integer
arr String
str Int
0
else case String
str of
[] -> Integer -> ST s Integer
forall a. a -> ST s a
forall (m :: * -> *) a. Monad m => a -> m a
return Integer
integer0
Char
a:String
bs -> do
MutableArray (PrimState (ST s)) Integer
-> Int -> Integer -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> a -> m ()
writeArray MutableArray s Integer
MutableArray (PrimState (ST s)) Integer
arr Int
0 (Integer -> ST s ()) -> Integer -> ST s ()
forall a b. (a -> b) -> a -> b
$ Char -> Integer
fromChar Char
a
MutableArray s Integer -> String -> Int -> ST s Integer
forall s. MutableArray s Integer -> String -> Int -> ST s Integer
loop MutableArray s Integer
arr String
bs Int
1
where
len' :: Int
len' = (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2
loop :: MutableArray s Integer -> String -> Int -> ST s Integer
loop :: forall s. MutableArray s Integer -> String -> Int -> ST s Integer
loop !MutableArray s Integer
arr (Char
a:Char
b:String
cs) !Int
o | Int
o Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len' = do
MutableArray (PrimState (ST s)) Integer
-> Int -> Integer -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> a -> m ()
writeArray MutableArray s Integer
MutableArray (PrimState (ST s)) Integer
arr Int
o (Integer -> ST s ()) -> Integer -> ST s ()
forall a b. (a -> b) -> a -> b
$! Char -> Integer
fromChar Char
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
10 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Char -> Integer
fromChar Char
b
MutableArray s Integer -> String -> Int -> ST s Integer
forall s. MutableArray s Integer -> String -> Int -> ST s Integer
loop MutableArray s Integer
arr String
cs (Int
o Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
loop MutableArray s Integer
arr String
_ Int
_ = MutableArray s Integer -> Int -> Integer -> ST s Integer
forall s. MutableArray s Integer -> Int -> Integer -> ST s Integer
algorithm MutableArray s Integer
arr Int
len' Integer
100
algorithm
:: forall s. MutableArray s Integer
-> Int
-> Integer
-> ST s Integer
algorithm :: forall s. MutableArray s Integer -> Int -> Integer -> ST s Integer
algorithm !MutableArray s Integer
arr !Int
len !Integer
base
| Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
40 = Integer -> Int -> ST s Integer
finish Integer
0 Int
0
| Int -> Bool
forall a. Integral a => a -> Bool
even Int
len = Int -> Int -> ST s Integer
loop Int
0 Int
0
| Bool
otherwise = Int -> Int -> ST s Integer
loop Int
1 Int
1
where
loop :: Int -> Int -> ST s Integer
loop :: Int -> Int -> ST s Integer
loop !Int
i !Int
o | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = do
Integer
a <- MutableArray (PrimState (ST s)) Integer -> Int -> ST s Integer
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> m a
readArray MutableArray s Integer
MutableArray (PrimState (ST s)) Integer
arr Int
i
Integer
b <- MutableArray (PrimState (ST s)) Integer -> Int -> ST s Integer
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> m a
readArray MutableArray s Integer
MutableArray (PrimState (ST s)) Integer
arr (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
MutableArray (PrimState (ST s)) Integer
-> Int -> Integer -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> a -> m ()
writeArray MutableArray s Integer
MutableArray (PrimState (ST s)) Integer
arr Int
i Integer
integer0
MutableArray (PrimState (ST s)) Integer
-> Int -> Integer -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> a -> m ()
writeArray MutableArray s Integer
MutableArray (PrimState (ST s)) Integer
arr (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Integer
integer0
MutableArray (PrimState (ST s)) Integer
-> Int -> Integer -> ST s ()
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> a -> m ()
writeArray MutableArray s Integer
MutableArray (PrimState (ST s)) Integer
arr Int
o (Integer -> ST s ()) -> Integer -> ST s ()
forall a b. (a -> b) -> a -> b
$! Integer
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
base Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
b
Int -> Int -> ST s Integer
loop (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) (Int
o Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
loop Int
_ Int
_ = MutableArray s Integer -> Int -> Integer -> ST s Integer
forall s. MutableArray s Integer -> Int -> Integer -> ST s Integer
algorithm MutableArray s Integer
arr Int
len' Integer
base'
where
!base' :: Integer
base' = Integer
base Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
base
!len' :: Int
len' = (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2
finish :: Integer -> Int -> ST s Integer
finish :: Integer -> Int -> ST s Integer
finish !Integer
acc !Int
i | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = do
Integer
a <- MutableArray (PrimState (ST s)) Integer -> Int -> ST s Integer
forall (m :: * -> *) a.
PrimMonad m =>
MutableArray (PrimState m) a -> Int -> m a
readArray MutableArray s Integer
MutableArray (PrimState (ST s)) Integer
arr Int
i
Integer -> Int -> ST s Integer
finish (Integer
acc Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
base Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
a) (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
finish !Integer
acc !Int
_ =
Integer -> ST s Integer
forall a. a -> ST s a
forall (m :: * -> *) a. Monad m => a -> m a
return Integer
acc
integer0 :: Integer
integer0 :: Integer
integer0 = Integer
0