{-# LANGUAGE BangPatterns, CPP, MagicHash, OverloadedStrings, UnboxedTuples #-}
module Blaze.Text.Int
(
digit
, integral
, minus
) where
import Blaze.ByteString.Builder
import Blaze.ByteString.Builder.Char8
import Data.ByteString.Char8 ()
import Data.Int (Int8, Int16, Int32, Int64)
import Data.Monoid (mappend, mempty)
import Data.Word (Word, Word8, Word16, Word32, Word64)
import GHC.Base (quotInt, remInt)
import GHC.Num (quotRemInteger)
import GHC.Types (Int(..))
#if defined(INTEGER_GMP)
import GHC.Integer.GMP.Internals
#elif defined(INTEGER_SIMPLE)
import GHC.Integer.Simple.Internals
#endif
#define PAIR(a,b) (# a,b #)
integral :: (Integral a, Show a) => a -> Builder
{-# RULES "integral/Int" integral = bounded :: Int -> Builder #-}
{-# RULES "integral/Int8" integral = bounded :: Int8 -> Builder #-}
{-# RULES "integral/Int16" integral = bounded :: Int16 -> Builder #-}
{-# RULES "integral/Int32" integral = bounded :: Int32 -> Builder #-}
{-# RULES "integral/Int64" integral = bounded :: Int64 -> Builder #-}
{-# RULES "integral/Word" integral = nonNegative :: Word -> Builder #-}
{-# RULES "integral/Word8" integral = nonNegative :: Word8 -> Builder #-}
{-# RULES "integral/Word16" integral = nonNegative :: Word16 -> Builder #-}
{-# RULES "integral/Word32" integral = nonNegative :: Word32 -> Builder #-}
{-# RULES "integral/Word64" integral = nonNegative :: Word64 -> Builder #-}
{-# RULES "integral/Integer" integral = integer :: Integer -> Builder #-}
integral :: a -> Builder
integral i :: a
i
| a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= 0 = a -> Builder
forall a. Integral a => a -> Builder
nonNegative a
i
| Builder -> ByteString
toByteString Builder
b ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== "-0" = String -> Builder
fromString (a -> String
forall a. Show a => a -> String
show a
i)
| Bool
otherwise = Builder
b
where b :: Builder
b = Builder
minus Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` a -> Builder
forall a. Integral a => a -> Builder
nonNegative (-a
i)
{-# NOINLINE integral #-}
bounded :: (Bounded a, Integral a) => a -> Builder
{-# SPECIALIZE bounded :: Int -> Builder #-}
{-# SPECIALIZE bounded :: Int8 -> Builder #-}
{-# SPECIALIZE bounded :: Int16 -> Builder #-}
{-# SPECIALIZE bounded :: Int32 -> Builder #-}
{-# SPECIALIZE bounded :: Int64 -> Builder #-}
bounded :: a -> Builder
bounded i :: a
i
| a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= 0 = a -> Builder
forall a. Integral a => a -> Builder
nonNegative a
i
| a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
forall a. Bounded a => a
minBound = Builder
minus Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` a -> Builder
forall a. Integral a => a -> Builder
nonNegative (-a
i)
| Bool
otherwise = Builder
minus Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend`
a -> Builder
forall a. Integral a => a -> Builder
nonNegative (a -> a
forall a. Num a => a -> a
negate (a
k a -> a -> a
forall a. Integral a => a -> a -> a
`quot` 10)) Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend`
a -> Builder
forall a. Integral a => a -> Builder
digit (a -> a
forall a. Num a => a -> a
negate (a
k a -> a -> a
forall a. Integral a => a -> a -> a
`rem` 10))
where k :: a
k = a
forall a. Bounded a => a
minBound a -> a -> a
forall a. a -> a -> a
`asTypeOf` a
i
nonNegative :: Integral a => a -> Builder
{-# SPECIALIZE nonNegative :: Int -> Builder #-}
{-# SPECIALIZE nonNegative :: Int8 -> Builder #-}
{-# SPECIALIZE nonNegative :: Int16 -> Builder #-}
{-# SPECIALIZE nonNegative :: Int32 -> Builder #-}
{-# SPECIALIZE nonNegative :: Int64 -> Builder #-}
{-# SPECIALIZE nonNegative :: Word -> Builder #-}
{-# SPECIALIZE nonNegative :: Word8 -> Builder #-}
{-# SPECIALIZE nonNegative :: Word16 -> Builder #-}
{-# SPECIALIZE nonNegative :: Word32 -> Builder #-}
{-# SPECIALIZE nonNegative :: Word64 -> Builder #-}
nonNegative :: a -> Builder
nonNegative = a -> Builder
forall a. Integral a => a -> Builder
go
where
go :: a -> Builder
go n :: a
n | a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< 10 = a -> Builder
forall a. Integral a => a -> Builder
digit a
n
| Bool
otherwise = a -> Builder
go (a
n a -> a -> a
forall a. Integral a => a -> a -> a
`quot` 10) Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` a -> Builder
forall a. Integral a => a -> Builder
digit (a
n a -> a -> a
forall a. Integral a => a -> a -> a
`rem` 10)
digit :: Integral a => a -> Builder
digit :: a -> Builder
digit n :: a
n = Word8 -> Builder
fromWord8 (Word8 -> Builder) -> Word8 -> Builder
forall a b. (a -> b) -> a -> b
$! a -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ 48
{-# INLINE digit #-}
minus :: Builder
minus :: Builder
minus = Word8 -> Builder
fromWord8 45
int :: Int -> Builder
int :: Int -> Builder
int = Int -> Builder
forall a. (Integral a, Show a) => a -> Builder
integral
{-# INLINE int #-}
integer :: Integer -> Builder
#if defined(INTEGER_GMP)
integer :: Integer -> Builder
integer (S# i# :: Int#
i#) = Int -> Builder
int (Int# -> Int
I# Int#
i#)
#endif
integer i :: Integer
i
| Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< 0 = Builder
minus Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` Integer -> Builder
go (-Integer
i)
| Bool
otherwise = Integer -> Builder
go Integer
i
where
go :: Integer -> Builder
go n :: Integer
n | Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
maxInt = Int -> Builder
int (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
| Bool
otherwise = [Integer] -> Builder
putH (Integer -> Integer -> [Integer]
splitf (Integer
maxInt Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
maxInt) Integer
n)
splitf :: Integer -> Integer -> [Integer]
splitf p :: Integer
p n :: Integer
n
| Integer
p Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
n = [Integer
n]
| Bool
otherwise = Integer -> [Integer] -> [Integer]
splith Integer
p (Integer -> Integer -> [Integer]
splitf (Integer
pInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
p) Integer
n)
splith :: Integer -> [Integer] -> [Integer]
splith p :: Integer
p (n :: Integer
n:ns :: [Integer]
ns) = case Integer
n Integer -> Integer -> (# Integer, Integer #)
`quotRemInteger` Integer
p of
PAIR(r :: Integer
q,r) | Integer
q Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> 0 -> Integer
q Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
: Integer
r Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
: Integer -> [Integer] -> [Integer]
splitb Integer
p [Integer]
ns
| Bool
otherwise -> Integer
r Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
: Integer -> [Integer] -> [Integer]
splitb Integer
p [Integer]
ns
splith _ _ = String -> [Integer]
forall a. HasCallStack => String -> a
error "splith: the impossible happened."
splitb :: Integer -> [Integer] -> [Integer]
splitb p :: Integer
p (n :: Integer
n:ns :: [Integer]
ns) = case Integer
n Integer -> Integer -> (# Integer, Integer #)
`quotRemInteger` Integer
p of
PAIR(r :: Integer
q,r) -> Integer
q Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
: Integer
r Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
: Integer -> [Integer] -> [Integer]
splitb Integer
p [Integer]
ns
splitb _ _ = []
data T = T !Integer !Int
fstT :: T -> Integer
fstT :: T -> Integer
fstT (T a :: Integer
a _) = Integer
a
maxInt :: Integer
maxDigits :: Int
T maxInt :: Integer
maxInt maxDigits :: Int
maxDigits =
(T -> Bool) -> (T -> T) -> T -> T
forall a. (a -> Bool) -> (a -> a) -> a -> a
until ((Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>Integer
mi) (Integer -> Bool) -> (T -> Integer) -> T -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
*10) (Integer -> Integer) -> (T -> Integer) -> T -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. T -> Integer
fstT) (\(T n :: Integer
n d :: Int
d) -> Integer -> Int -> T
T (Integer
nInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
*10) (Int
dInt -> Int -> Int
forall a. Num a => a -> a -> a
+1)) (Integer -> Int -> T
T 10 1)
where mi :: Integer
mi = Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
forall a. Bounded a => a
maxBound :: Int)
putH :: [Integer] -> Builder
putH :: [Integer] -> Builder
putH (n :: Integer
n:ns :: [Integer]
ns) = case Integer
n Integer -> Integer -> (# Integer, Integer #)
`quotRemInteger` Integer
maxInt of
PAIR(y :: Integer
x,y)
| Int
q Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 0 -> Int -> Builder
int Int
q Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` Int -> Builder
pblock Int
r Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` [Integer] -> Builder
putB [Integer]
ns
| Bool
otherwise -> Int -> Builder
int Int
r Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` [Integer] -> Builder
putB [Integer]
ns
where q :: Int
q = Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
x
r :: Int
r = Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
y
putH _ = String -> Builder
forall a. HasCallStack => String -> a
error "putH: the impossible happened"
putB :: [Integer] -> Builder
putB :: [Integer] -> Builder
putB (n :: Integer
n:ns :: [Integer]
ns) = case Integer
n Integer -> Integer -> (# Integer, Integer #)
`quotRemInteger` Integer
maxInt of
PAIR(y :: Integer
x,y) -> Int -> Builder
pblock Int
q Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` Int -> Builder
pblock Int
r Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` [Integer] -> Builder
putB [Integer]
ns
where q :: Int
q = Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
x
r :: Int
r = Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
y
putB _ = Builder
forall a. Monoid a => a
mempty
pblock :: Int -> Builder
pblock :: Int -> Builder
pblock = Int -> Int -> Builder
forall t. (Eq t, Num t) => t -> Int -> Builder
go Int
maxDigits
where
go :: t -> Int -> Builder
go !t
d !Int
n
| t
d t -> t -> Bool
forall a. Eq a => a -> a -> Bool
== 1 = Int -> Builder
forall a. Integral a => a -> Builder
digit Int
n
| Bool
otherwise = t -> Int -> Builder
go (t
dt -> t -> t
forall a. Num a => a -> a -> a
-1) Int
q Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
`mappend` Int -> Builder
forall a. Integral a => a -> Builder
digit Int
r
where q :: Int
q = Int
n Int -> Int -> Int
`quotInt` 10
r :: Int
r = Int
n Int -> Int -> Int
`remInt` 10