Skip to content

Commit 56c718c

Browse files
committed
Speed up replicate for lazy Text
1 parent ed93c4c commit 56c718c

File tree

1 file changed

+26
-22
lines changed

1 file changed

+26
-22
lines changed

src/Data/Text/Lazy.hs

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{-# LANGUAGE BangPatterns, MagicHash, CPP, TypeFamilies #-}
33
{-# LANGUAGE Trustworthy #-}
44
{-# LANGUAGE TemplateHaskellQuotes #-}
5+
{-# LANGUAGE LambdaCase #-}
56

67
-- |
78
-- Module : Data.Text.Lazy
@@ -199,7 +200,7 @@ module Data.Text.Lazy
199200

200201
import Prelude (Char, Bool(..), Maybe(..), String,
201202
Eq(..), Ord(..), Ordering(..), Read(..), Show(..),
202-
(&&), (||), (+), (-), (.), ($), (++),
203+
(&&), (+), (-), (.), ($), (++),
203204
error, flip, fmap, fromIntegral, not, otherwise, quot)
204205
import qualified Prelude as P
205206
import Control.DeepSeq (NFData(..))
@@ -221,7 +222,7 @@ import qualified Data.Text.Internal.Lazy.Fusion as S
221222
import Data.Text.Internal.Fusion.Types (PairS(..))
222223
import Data.Text.Internal.Lazy.Fusion (stream, unstream)
223224
import Data.Text.Internal.Lazy (Text(..), chunk, empty, foldlChunks,
224-
foldrChunks, smallChunkSize, equal)
225+
foldrChunks, smallChunkSize, defaultChunkSize, equal)
225226
import Data.Text.Internal (firstf, safe, text)
226227
import Data.Text.Lazy.Encoding (decodeUtf8', encodeUtf8)
227228
import Data.Text.Internal.Lazy.Search (indices)
@@ -591,7 +592,7 @@ intersperse c t = unstream (S.intersperse (safe c) (stream t))
591592
justifyLeft :: Int64 -> Char -> Text -> Text
592593
justifyLeft k c t
593594
| len >= k = t
594-
| otherwise = t `append` replicateChar (k-len) c
595+
| otherwise = t `append` replicateChunk (k-len) (T.singleton c)
595596
where len = length t
596597
{-# INLINE [1] justifyLeft #-}
597598

@@ -606,7 +607,7 @@ justifyLeft k c t
606607
justifyRight :: Int64 -> Char -> Text -> Text
607608
justifyRight k c t
608609
| len >= k = t
609-
| otherwise = replicateChar (k-len) c `append` t
610+
| otherwise = replicateChunk (k-len) (T.singleton c) `append` t
610611
where len = length t
611612
{-# INLINE justifyRight #-}
612613

@@ -620,7 +621,7 @@ justifyRight k c t
620621
center :: Int64 -> Char -> Text -> Text
621622
center k c t
622623
| len >= k = t
623-
| otherwise = replicateChar l c `append` t `append` replicateChar r c
624+
| otherwise = replicateChunk l (T.singleton c) `append` t `append` replicateChunk r (T.singleton c)
624625
where len = length t
625626
d = k - len
626627
r = d `quot` 2
@@ -910,14 +911,28 @@ repeat c = let t = Chunk (T.replicate smallChunkSize (T.singleton c)) t
910911
-- | /O(n*m)/ 'replicate' @n@ @t@ is a 'Text' consisting of the input
911912
-- @t@ repeated @n@ times.
912913
replicate :: Int64 -> Text -> Text
913-
replicate n t
914-
| null t || n <= 0 = empty
915-
| isSingleton t = replicateChar n (head t)
916-
| otherwise = concat (rep 0)
917-
where rep !i | i >= n = []
918-
| otherwise = t : rep (i+1)
914+
replicate n
915+
| n <= 0 = P.const Empty
916+
| otherwise = \case
917+
Empty -> Empty
918+
Chunk t Empty -> replicateChunk n t
919+
t -> concat (rep n)
920+
where
921+
rep 0 = []
922+
rep i = t : rep (i - 1)
919923
{-# INLINE [1] replicate #-}
920924

925+
replicateChunk :: Int64 -> T.Text -> Text
926+
replicateChunk !n !t@(T.Text _ _ len)
927+
| n <= 0 = Empty
928+
| otherwise = Chunk headChunk $ P.foldr Chunk Empty (L.genericReplicate q normalChunk)
929+
where
930+
perChunk = defaultChunkSize `quot` len
931+
normalChunk = T.replicate perChunk t
932+
(q, r) = n `P.quotRem` intToInt64 perChunk
933+
headChunk = T.replicate (int64ToInt r) t
934+
{-# INLINE replicateChunk #-}
935+
921936
-- | 'cycle' ties a finite, non-empty 'Text' into a circular one, or
922937
-- equivalently, the infinite repetition of the original 'Text'.
923938
--
@@ -937,17 +952,6 @@ iterate :: (Char -> Char) -> Char -> Text
937952
iterate f c = let t c' = Chunk (T.singleton c') (t (f c'))
938953
in t c
939954

940-
-- | /O(n)/ 'replicateChar' @n@ @c@ is a 'Text' of length @n@ with @c@ the
941-
-- value of every element.
942-
replicateChar :: Int64 -> Char -> Text
943-
replicateChar n c = unstream (S.replicateCharI n (safe c))
944-
{-# INLINE replicateChar #-}
945-
946-
{-# RULES
947-
"LAZY TEXT replicate/singleton -> replicateChar" [~1] forall n c.
948-
replicate n (singleton c) = replicateChar n c
949-
#-}
950-
951955
-- | /O(n)/, where @n@ is the length of the result. The 'unfoldr'
952956
-- function is analogous to the List 'L.unfoldr'. 'unfoldr' builds a
953957
-- 'Text' from a seed value. The function takes the element and

0 commit comments

Comments
 (0)