@@ -1,4 +1,4 @@
1−{-# LANGUAGE BangPatterns, CPP, MagicHash, UnboxedTuples #-}
1+{-# LANGUAGE BangPatterns, CPP, MagicHash, RankNTypes, UnboxedTuples #-}
3-- Module: Data.Text.Lazy.Builder.Int
3-- Module: Data.Text.Lazy.Builder.Int
4-- Copyright: (c) 2011 MailRank, Inc.
4-- Copyright: (c) 2011 MailRank, Inc.
@@ -19,10 +19,12 @@ import Data.Int (Int8, Int16, Int32, Int64)
19import Data.Monoid (mempty)
19import Data.Monoid (mempty)
20import Data.Text.Lazy.Builder.Functions ((<>), i2d)
20import Data.Text.Lazy.Builder.Functions ((<>), i2d)
21import Data.Text.Lazy.Builder.Internal
21import Data.Text.Lazy.Builder.Internal
22+import Data.Text.Array
22import Data.Word (Word, Word8, Word16, Word32, Word64)
23import Data.Word (Word, Word8, Word16, Word32, Word64)
23import GHC.Base (quotInt, remInt)
24import GHC.Base (quotInt, remInt)
24import GHC.Num (quotRemInteger)
25import GHC.Num (quotRemInteger)
25import GHC.Types (Int(..))
26import GHC.Types (Int(..))
27+import Control.Monad.ST
27#ifdef __GLASGOW_HASKELL__
29#ifdef __GLASGOW_HASKELL__
28# if __GLASGOW_HASKELL__ < 611
30# if __GLASGOW_HASKELL__ < 611
@@ -69,14 +71,16 @@ decimal' :: (Integral a) => (a -> Bool) -> a -> Builder
69decimal' p i
71decimal' p i
70 | i < 0 = if p i
72 | i < 0 = if p i
71 then let j = -(i `quot` 10)
73 then let j = -(i `quot` 10)
72− n = countDigits j + 2
74+ !n = countDigits j
73− in go n $ singleton '-' <>
75+ in writeN (n + 2) $ \marr off -> do
74− positive j <> digit (-(i `rem` 10))
76+ unsafeWrite marr off minus
77+ posDecimal marr (off+1) n j
78+ unsafeWrite marr (off+n+1) (i2w (-(i `rem` 10)))
75 else let j = -i
79 else let j = -i
76− n = countDigits j + 1
80+ !n = countDigits j
77− in go n $ singleton '-' <> positive j
81+ in writeN (n + 1) $ \marr off ->
82+ unsafeWrite marr off minus >> posDecimal marr (off+1) n j
78− | otherwise = go (countDigits i) $ positive i
83+ | otherwise = positive i
79− where go k b = ensureFree k `append'` b
81positive :: (Integral a) => a -> Builder
85positive :: (Integral a) => a -> Builder
82{-# SPECIALIZE positive :: Int -> Builder #-}
86{-# SPECIALIZE positive :: Int -> Builder #-}
@@ -89,9 +93,29 @@ positive :: (Integral a) => a -> Builder
89{-# SPECIALIZE positive :: Word16 -> Builder #-}
93{-# SPECIALIZE positive :: Word16 -> Builder #-}
90{-# SPECIALIZE positive :: Word32 -> Builder #-}
94{-# SPECIALIZE positive :: Word32 -> Builder #-}
91{-# SPECIALIZE positive :: Word64 -> Builder #-}
95{-# SPECIALIZE positive :: Word64 -> Builder #-}
92−positive = go
96+positive i
97+ | i < 10 = writeN 1 $ \marr off -> unsafeWrite marr off (i2w i)
98+ | otherwise = let !n = countDigits i
99+ in writeN n $ \marr off -> posDecimal marr off n i
101+posDecimal :: Integral a => forall s. MArray s -> Int -> Int -> a -> ST s ()
102+{-# INLINE posDecimal #-}
103+posDecimal marr off0 ds v0 = go (off0 + ds - 1) v0
93− where go n | n < 10 = digit n
104+ where go off v
105+ | v < 10 = unsafeWrite marr off (i2w v)
94− | otherwise = go (n `quot` 10) <> digit (n `rem` 10)
106+ | otherwise = do
107+ unsafeWrite marr off (i2w (v `rem` 10))
108+ go (off-1) (v `div` 10)
110+minus, zero :: Word16
116+i2w :: (Integral a) => a -> Word16
118+i2w v = zero + fromIntegral v
96countDigits :: (Integral a) => a -> Int
120countDigits :: (Integral a) => a -> Int
97{-# INLINE countDigits #-}
121{-# INLINE countDigits #-}