on master help sign in
Use unchecked shifts for a speedup.

--HG-- extra : convert_revision : 0af617e20297244e7dc2c99de8af3fe7cfd01ec2

commit62aa9687ba87a0f2c2c14fdf9ff4d2ab93bed13d authorBryan O'Sullivan <bos@serpentine.com> dateWed 3 Jun 2009, 06:05 (17 years ago) parent47f25e1
7 files changed+77−5
Data/Text/Encoding/Fusion.hs+1−1 Data/Text/Encoding/Fusion/Common.hs+2−1 Data/Text/Encoding/Utf8.hs+2−1 Data/Text/Fusion.hs+2−1 Data/Text/UnsafeChar.hs+2−1 Data/Text/UnsafeShift.hs+67 text.cabal+1
Data/Text/Encoding/Fusion.hs+1−1
@@ -32,12 +32,12 @@ module Data.Text.Encoding.Fusion
3232 ) where
3333
3434import Control.Exception (assert)
35−import Data.Bits (shiftL)
3635import Data.ByteString as B
3736import Data.ByteString.Internal (ByteString(..), mallocByteString, memcpy)
3837import Data.Text.Fusion (Step(..), Stream(..))
3938import Data.Text.Encoding.Fusion.Common
4039import Data.Text.UnsafeChar (unsafeChr, unsafeChr8, unsafeChr32)
40+import Data.Text.UnsafeShift (shiftL)
4141import Data.Word (Word8, Word16, Word32)
4242import Foreign.ForeignPtr (withForeignPtr, ForeignPtr)
4343import Foreign.Storable (pokeByteOff)
Data/Text/Encoding/Fusion/Common.hs+2−1
@@ -27,10 +27,11 @@ module Data.Text.Encoding.Fusion.Common
2727 , restreamUtf32BE
2828 ) where
2929
30−import Data.Bits (shiftR, (.&.))
30+import Data.Bits ((.&.))
3131import Data.Char (ord)
3232import Data.Text.Fusion (Step(..), Stream(..))
3333import Data.Text.Fusion.Internal (M(..), S(..))
34+import Data.Text.UnsafeShift (shiftR)
3435import Data.Word (Word8)
3536import qualified Data.Text.Encoding.Utf8 as U8
3637
Data/Text/Encoding/Utf8.hs+2−1
@@ -32,7 +32,8 @@ module Data.Text.Encoding.Utf8
3232
3333import Control.Exception (assert)
3434import Data.Char (ord)
35−import Data.Bits (shiftR, (.&.))
35+import Data.Bits ((.&.))
36+import Data.Text.UnsafeShift (shiftR)
3637import GHC.Exts
3738import GHC.Word (Word8(..))
3839
Data/Text/Fusion.hs+2−1
@@ -50,10 +50,11 @@ module Data.Text.Fusion
5050import Prelude (Bool(..), Char, Eq(..), Maybe(..), Monad(..), Int,
5151 Num(..), Ord(..), ($), (&&),
5252 fromIntegral, otherwise)
53−import Data.Bits ((.&.), shiftR)
53+import Data.Bits ((.&.))
5454import Data.Char (ord)
5555import Data.Text.Internal (Text(..))
5656import Data.Text.UnsafeChar (unsafeChr, unsafeWrite)
57+import Data.Text.UnsafeShift (shiftR)
5758import qualified Data.Text.Array as A
5859import qualified Data.Text.Fusion.Common as S
5960import Data.Text.Fusion.Internal
Data/Text/UnsafeChar.hs+2−1
@@ -24,8 +24,9 @@ module Data.Text.UnsafeChar
2424
2525import Control.Exception (assert)
2626import Control.Monad.ST (ST)
27−import Data.Bits ((.&.), shiftR)
27+import Data.Bits ((.&.))
2828import Data.Char (ord)
29+import Data.Text.UnsafeShift (shiftR)
2930import GHC.Exts (Char(..), chr#, word2Int#)
3031import GHC.Word (Word8(..), Word16(..), Word32(..))
3132import qualified Data.Text.Array as A
Data/Text/UnsafeShift.hsnew file+67
@@ -0,0 +1,67 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+-- |
4+-- Module : Data.Text.UnsafeShift
5+-- Copyright : (c) Bryan O'Sullivan 2009
6+--
7+-- License : BSD-style
8+-- Maintainer : bos@serpentine.com, rtharper@aftereternity.co.uk,
9+-- duncan@haskell.org
10+-- Stability : experimental
11+-- Portability : GHC
12+--
13+-- Fast, unchecked bit shifting functions.
14+
15+module Data.Text.UnsafeShift
16+ (
17+ UnsafeShift(..)
18+ ) where
19+
20+import qualified Data.Bits as Bits
21+import GHC.Base
22+import GHC.Word
23+
24+-- | This is a workaround for poor optimisation in GHC 6.8.2. It
25+-- fails to notice constant-width shifts, and adds a test and branch
26+-- to every shift. This imposes about a 10% performance hit.
27+--
28+-- These functions are undefined when the amount being shifted by is
29+-- greater than the size in bits of a machine Int#.
30+class UnsafeShift a where
31+ shiftL :: a -> Int -> a
32+ shiftR :: a -> Int -> a
33+
34+instance UnsafeShift Word16 where
35+ {-# INLINE shiftL #-}
36+ shiftL (W16# x#) (I# i#) = W16# (x# `uncheckedShiftL#` i#)
37+
38+ {-# INLINE shiftR #-}
39+ shiftR (W16# x#) (I# i#) = W16# (x# `uncheckedShiftRL#` i#)
40+
41+instance UnsafeShift Word32 where
42+ {-# INLINE shiftL #-}
43+ shiftL (W32# x#) (I# i#) = W32# (x# `uncheckedShiftL#` i#)
44+
45+ {-# INLINE shiftR #-}
46+ shiftR (W32# x#) (I# i#) = W32# (x# `uncheckedShiftRL#` i#)
47+
48+instance UnsafeShift Word64 where
49+ {-# INLINE shiftL #-}
50+ shiftL (W64# x#) (I# i#) = W64# (x# `uncheckedShiftL64#` i#)
51+
52+ {-# INLINE shiftR #-}
53+ shiftR (W64# x#) (I# i#) = W64# (x# `uncheckedShiftRL64#` i#)
54+
55+instance UnsafeShift Int where
56+ {-# INLINE shiftL #-}
57+ shiftL (I# x#) (I# i#) = I# (x# `iShiftL#` i#)
58+
59+ {-# INLINE shiftR #-}
60+ shiftR (I# x#) (I# i#) = I# (x# `iShiftRA#` i#)
61+
62+instance UnsafeShift Integer where
63+ {-# INLINE shiftL #-}
64+ shiftL = Bits.shiftL
65+
66+ {-# INLINE shiftR #-}
67+ shiftR = Bits.shiftR
text.cabal+1
@@ -34,6 +34,7 @@ library
3434 Data.Text.Lazy.Internal
3535 Data.Text.Unsafe
3636 Data.Text.UnsafeChar
37+ Data.Text.UnsafeShift
3738 Data.Text.Encoding.Utf8
3839 Data.Text.Encoding.Utf16
3940 Data.Text.Encoding.Utf32