on master help sign in
Switch to a faster decimal algorithm
481cec9Bryan O'Sullivan
Data/Text/Lazy/Builder/Int.hs+14−5
@@ -18,8 +18,10 @@ module Data.Text.Lazy.Builder.Int
18
18
19import Data.Int (Int8, Int16, Int32, Int64)
19import Data.Int (Int8, Int16, Int32, Int64)
20import Data.Monoid (mempty)
20import Data.Monoid (mempty)
21+import qualified Data.ByteString.Unsafe as B
21import Data.Text.Lazy.Builder.Functions ((<>), i2d)
22import Data.Text.Lazy.Builder.Functions ((<>), i2d)
22import Data.Text.Lazy.Builder.Internal
23import Data.Text.Lazy.Builder.Internal
24+import Data.Text.Lazy.Builder.Int.Digits (digits)
23import Data.Text.Array
25import Data.Text.Array
24import Data.Word (Word, Word8, Word16, Word32, Word64)
26import Data.Word (Word, Word8, Word16, Word32, Word64)
25import GHC.Base (quotInt, remInt)
27import GHC.Base (quotInt, remInt)
@@ -99,14 +101,21 @@ positive i
99 | otherwise = let !n = countDigits i
101 | otherwise = let !n = countDigits i
100 in writeN n $ \marr off -> posDecimal marr off n i
102 in writeN n $ \marr off -> posDecimal marr off n i
101
103
104+posDecimal :: (Integral a) =>
102−posDecimal :: Integral a => forall s. MArray s -> Int -> Int -> a -> ST s ()
105+ forall s. MArray s -> Int -> Int -> a -> ST s ()
103{-# INLINE posDecimal #-}
106{-# INLINE posDecimal #-}
104posDecimal marr off0 ds v0 = go (off0 + ds - 1) v0
107posDecimal marr off0 ds v0 = go (off0 + ds - 1) v0
105 where go off v
108 where go off v
106− | v < 10 = unsafeWrite marr off (i2w v)
109+ | v >= 100 = do
107− | otherwise = do
110+ write2 off $ let u = v `rem` 100
108− unsafeWrite marr off (i2w (v `rem` 10))
111+ in u + u
109− go (off-1) (v `quot` 10)
112+ go (off - 2) (v `quot` 100)
113+ | v < 10 = unsafeWrite marr off (i2w v)
114+ | otherwise = write2 off (v + v)
115+ write2 off i = do
116+ unsafeWrite marr off $ get (i + 1)
117+ unsafeWrite marr (off - 1) $ get i
118+ get i = fromIntegral $ B.unsafeIndex digits (fromIntegral i) :: Word16
110
119
111minus, zero :: Word16
120minus, zero :: Word16
112{-# INLINE minus #-}
121{-# INLINE minus #-}
Data/Text/Lazy/Builder/Int/Digits.hsnew file+22
@@ -0,0 +1,22 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+
3+-- Module: Data.Text.Lazy.Builder.Int.Digits
4+-- Copyright: (c) 2013 Bryan O'Sullivan
5+-- License: BSD3
6+-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>
7+-- Stability: experimental
8+-- Portability: portable
9+--
10+-- This module exists because the C preprocessor does things that we
11+-- shall not speak of when confronted with Haskell multiline strings.
12+
13+module Data.Text.Lazy.Builder.Int.Digits (digits) where
14+
15+import Data.ByteString.Char8 (ByteString)
16+
17+digits :: ByteString
18+digits = "0001020304050607080910111213141516171819\
19+ \2021222324252627282930313233343536373839\
20+ \4041424344454647484950515253545556575859\
21+ \6061626364656667686970717273747576777879\
22+ \8081828384858687888990919293949596979899"
tests/text-tests.cabal+1
@@ -87,6 +87,7 @@ library
87 Data.Text.Lazy.Builder
87 Data.Text.Lazy.Builder
88 Data.Text.Lazy.Builder.Functions
88 Data.Text.Lazy.Builder.Functions
89 Data.Text.Lazy.Builder.Int
89 Data.Text.Lazy.Builder.Int
90+ Data.Text.Lazy.Builder.Int.Digits
90 Data.Text.Lazy.Builder.Internal
91 Data.Text.Lazy.Builder.Internal
91 Data.Text.Lazy.Builder.RealFloat
92 Data.Text.Lazy.Builder.RealFloat
92 Data.Text.Lazy.Builder.RealFloat.Functions
93 Data.Text.Lazy.Builder.RealFloat.Functions
text.cabal+1
@@ -109,6 +109,7 @@ library
109 Data.Text.Fusion.Size
109 Data.Text.Fusion.Size
110 Data.Text.IO.Internal
110 Data.Text.IO.Internal
111 Data.Text.Lazy.Builder.Functions
111 Data.Text.Lazy.Builder.Functions
112+ Data.Text.Lazy.Builder.Int.Digits
112 Data.Text.Lazy.Builder.Internal
113 Data.Text.Lazy.Builder.Internal
113 Data.Text.Lazy.Builder.RealFloat.Functions
114 Data.Text.Lazy.Builder.RealFloat.Functions
114 Data.Text.Lazy.Encoding.Fusion
115 Data.Text.Lazy.Encoding.Fusion