@@ -1,9 +1,9 @@
1−{-# LANGUAGE BangPatterns, CPP, MagicHash, Rank2Types, RecordWildCards,
1+{-# LANGUAGE BangPatterns, CPP, ForeignFunctionInterface, MagicHash, Rank2Types,
2− UnboxedTuples #-}
2+ RecordWildCards, UnboxedTuples, UnliftedFFITypes #-}
3{-# OPTIONS_GHC -fno-warn-unused-matches #-}
3{-# OPTIONS_GHC -fno-warn-unused-matches #-}
5-- Module : Data.Text.Array
5-- Module : Data.Text.Array
6−-- Copyright : (c) 2009, 2010 Bryan O'Sullivan
6+-- Copyright : (c) 2009, 2010, 2011 Bryan O'Sullivan
8-- License : BSD-style
8-- License : BSD-style
9-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
9-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
@@ -60,14 +60,16 @@ if (_k_) < 0 || (_k_) >= (_len_) then error ("Data.Text.Array." ++ (_func_) ++ "
60#if defined(ASSERTS)
60#if defined(ASSERTS)
61import Control.Exception (assert)
61import Control.Exception (assert)
63+import Control.Monad.ST (unsafeIOToST)
63import Data.Bits ((.&.), xor)
64import Data.Bits ((.&.), xor)
65+import Data.Text.Unsafe.Base (inlinePerformIO)
64import Data.Text.UnsafeShift (shiftL, shiftR)
66import Data.Text.UnsafeShift (shiftL, shiftR)
67+import Foreign.C.Types (CInt, CSize)
65import GHC.Base (ByteArray#, MutableByteArray#, Int(..),
68import GHC.Base (ByteArray#, MutableByteArray#, Int(..),
66− indexWord16Array#, indexWordArray#, newByteArray#,
69+ indexWord16Array#, newByteArray#,
67− readWord16Array#, readWordArray#, unsafeCoerce#,
68− writeWord16Array#, writeWordArray#)
70+ unsafeCoerce#, writeWord16Array#)
69import GHC.ST (ST(..), runST)
71import GHC.ST (ST(..), runST)
70−import GHC.Word (Word16(..), Word(..))
72+import GHC.Word (Word16(..))
71import Prelude hiding (length, read)
73import Prelude hiding (length, read)
73-- | Immutable array type.
75-- | Immutable array type.
@@ -140,23 +142,6 @@ unsafeIndex Array{..} i@(I# i#) =
140 case indexWord16Array# aBA i# of r# -> (W16# r#)
142 case indexWord16Array# aBA i# of r# -> (W16# r#)
141{-# INLINE unsafeIndex #-}
143{-# INLINE unsafeIndex #-}
143−-- | Unchecked read of an immutable array. May return garbage or
144−-- crash on an out-of-bounds access.
145−unsafeIndexWord :: Array -> Int -> Word
146−unsafeIndexWord Array{..} i@(I# i#) =
147− CHECK_BOUNDS("unsafeIndexWord",aLen`div`wordFactor,i)
148− case indexWordArray# aBA i# of r# -> (W# r#)
149−{-# INLINE unsafeIndexWord #-}
151−-- | Unchecked read of a mutable array. May return garbage or
152−-- crash on an out-of-bounds access.
153−unsafeRead :: MArray s -> Int -> ST s Word16
154−unsafeRead MArray{..} i@(I# i#) = ST $ \s# ->
155− CHECK_BOUNDS("unsafeRead",maLen,i)
156− case readWord16Array# maBA i# s# of
157− (# s2#, r# #) -> (# s2#, W16# r# #)
158−{-# INLINE unsafeRead #-}
160-- | Unchecked write of a mutable array. May return garbage or crash
145-- | Unchecked write of a mutable array. May return garbage or crash
161-- on an out-of-bounds access.
146-- on an out-of-bounds access.
162unsafeWrite :: MArray s -> Int -> Word16 -> ST s ()
147unsafeWrite :: MArray s -> Int -> Word16 -> ST s ()
@@ -166,24 +151,6 @@ unsafeWrite MArray{..} i@(I# i#) (W16# e#) = ST $ \s1# ->
166 s2# -> (# s2#, () #)
151 s2# -> (# s2#, () #)
167{-# INLINE unsafeWrite #-}
152{-# INLINE unsafeWrite #-}
169−-- | Unchecked read of a mutable array. May return garbage or
170−-- crash on an out-of-bounds access.
171−unsafeReadWord :: MArray s -> Int -> ST s Word
172−unsafeReadWord MArray{..} i@(I# i#) = ST $ \s# ->
173− CHECK_BOUNDS("unsafeRead64",maLen`div`wordFactor,i)
174− case readWordArray# maBA i# s# of
175− (# s2#, r# #) -> (# s2#, W# r# #)
176−{-# INLINE unsafeReadWord #-}
178−-- | Unchecked write of a mutable array. May return garbage or crash
179−-- on an out-of-bounds access.
180−unsafeWriteWord :: MArray s -> Int -> Word -> ST s ()
181−unsafeWriteWord MArray{..} i@(I# i#) (W# e#) = ST $ \s1# ->
182− CHECK_BOUNDS("unsafeWriteWord",maLen`div`wordFactor,i)
183− case writeWordArray# maBA i# e# s1# of
184− s2# -> (# s2#, () #)
185−{-# INLINE unsafeWriteWord #-}
187-- | Convert an immutable array to a list.
154-- | Convert an immutable array to a list.
188toList :: Array -> Int -> Int -> [Word16]
155toList :: Array -> Int -> Int -> [Word16]
189toList ary off len = loop 0
156toList ary off len = loop 0
@@ -207,15 +174,6 @@ run2 k = runST (do
207 arr <- unsafeFreeze marr
174 arr <- unsafeFreeze marr
208 return (arr,b))
175 return (arr,b))
210−-- | The amount to divide or multiply by to switch between units of
211−-- 'Word16' and units of 'Word'.
213−wordFactor = SIZEOF_HSWORD `shiftR` 1
215−-- | Indicate whether an offset is word-aligned.
216−wordAligned :: Int -> Bool
217−wordAligned i = i .&. (wordFactor - 1) == 0
219-- | Copy some elements of a mutable array.
177-- | Copy some elements of a mutable array.
220copyM :: MArray s -- ^ Destination
178copyM :: MArray s -- ^ Destination
221 -> Int -- ^ Destination offset
179 -> Int -- ^ Destination offset
@@ -223,49 +181,33 @@ copyM :: MArray s -- ^ Destination
223 -> Int -- ^ Source offset
181 -> Int -- ^ Source offset
224 -> Int -- ^ Count
182 -> Int -- ^ Count
225 -> ST s ()
183 -> ST s ()
226−copyM dest didx src sidx count =
184+copyM dest didx src sidx count
185+ | count <= 0 = return ()
227#if defined(ASSERTS)
187#if defined(ASSERTS)
228 assert (sidx + count <= length src) .
188 assert (sidx + count <= length src) .
229− assert (didx + count <= length dest) $
189+ assert (didx + count <= length dest) .
231− if srem == 0 && drem == 0
191+ unsafeIOToST $ memcpyM (maBA dest) (fromIntegral didx)
232− then fast_loop 0
192+ (maBA src) (fromIntegral sidx)
233− else slow_loop 0
193+ (fromIntegral count)
234− where
194+{-# INLINE copyM #-}
235− (swidx,srem) = sidx `divMod` wordFactor
236− (dwidx,drem) = didx `divMod` wordFactor
237− nwds = count `div` wordFactor
239− | i >= nwds = slow_loop (i * wordFactor)
240− | otherwise = do w <- unsafeReadWord src (swidx+i)
241− unsafeWriteWord dest (dwidx+i) w
244− | i >= count= return ()
245− | otherwise = do unsafeRead src (sidx+i) >>= unsafeWrite dest (didx+i)
248-- | Copy some elements of an immutable array.
196-- | Copy some elements of an immutable array.
249copyI :: MArray s -- ^ Destination
197copyI :: MArray s -- ^ Destination
250 -> Int -- ^ Destination offset
198 -> Int -- ^ Destination offset
251 -> Array -- ^ Source
199 -> Array -- ^ Source
252 -> Int -- ^ Source offset
200 -> Int -- ^ Source offset
253− -> Int -- ^ First offset in source /not/ to
201+ -> Int -- ^ First offset in destination /not/ to
254 -- copy (i.e. /not/ length)
202 -- copy (i.e. /not/ length)
255 -> ST s ()
203 -> ST s ()
256copyI dest i0 src j0 top
204copyI dest i0 src j0 top
257− | wordAligned i0 && wordAligned j0 = fast (i0 `div` wordFactor) (j0 `div` wordFactor)
258− | otherwise = slow i0 j0
260− topwds = top `div` wordFactor
262− | i >= topwds = slow (i * wordFactor) (j * wordFactor)
263− | otherwise = do unsafeWriteWord dest i (src `unsafeIndexWord` j)
266− | i >= top = return ()
205+ | i0 >= top = return ()
267− | otherwise = do unsafeWrite dest i (src `unsafeIndex` j)
206+ | otherwise = unsafeIOToST $
268− slow (i+1) (j+1)
207+ memcpyI (maBA dest) (fromIntegral i0)
208+ (aBA src) (fromIntegral j0)
209+ (fromIntegral (top-i0))
270-- | Compare portions of two arrays for equality. No bounds checking
212-- | Compare portions of two arrays for equality. No bounds checking
271-- is performed.
213-- is performed.
@@ -275,22 +217,18 @@ equal :: Array -- ^ First
275 -> Int -- ^ Offset into second
217 -> Int -- ^ Offset into second
276 -> Int -- ^ Count
218 -> Int -- ^ Count
278−equal arrA offA arrB offB count
220+equal arrA offA arrB offB count = inlinePerformIO $ do
279− | wordAligned offA && wordAligned offB = fast 0
221+ i <- memcmp (aBA arrA) (fromIntegral offA)
280− | otherwise = slow 0
222+ (aBA arrB) (fromIntegral offB) (fromIntegral count)
281− where
223+ return $! i == 0
282− countWords = count `div` wordFactor
224+{-# INLINE equal #-}
284− | i >= countWords = slow (i * wordFactor)
226+foreign import ccall unsafe "_hs_text_memcpy" memcpyI
285− | a /= b = False
227+ :: MutableByteArray# s -> CSize -> ByteArray# -> CSize -> CSize -> IO ()
286− | otherwise = fast (i+1)
228+
287− where a = unsafeIndexWord arrA (offAW+i)
229+foreign import ccall unsafe "_hs_text_memcmp" memcmp
288− b = unsafeIndexWord arrB (offBW+i)
230+ :: ByteArray# -> CSize -> ByteArray# -> CSize -> CSize -> IO CInt
289− offAW = offA `div` wordFactor
231+
290− offBW = offB `div` wordFactor
232+foreign import ccall unsafe "_hs_text_memcpy" memcpyM
291− slow !i
233+ :: MutableByteArray# s -> CSize -> MutableByteArray# s -> CSize -> CSize
292− | i >= count = True
234+ -> IO ()
294− | otherwise = slow (i+1)
295− where a = unsafeIndex arrA (offA+i)
296− b = unsafeIndex arrB (offB+i)