on master help sign in
Tracking both upper and lower bounds in Size
f4fc30cEdward Kmett
Data/Text/Internal/Fusion.hs+3−3
@@ -51,7 +51,7 @@ module Data.Text.Internal.Fusion
51
51
52import Prelude (Bool(..), Char, Maybe(..), Monad(..), Int,
52import Prelude (Bool(..), Char, Maybe(..), Monad(..), Int,
53 Num(..), Ord(..), ($), (&&),
53 Num(..), Ord(..), ($), (&&),
54− fromIntegral, otherwise)
54+ fromIntegral, otherwise, quot)
55import Data.Bits ((.&.))
55import Data.Bits ((.&.))
56import Data.Text.Internal (Text(..))
56import Data.Text.Internal (Text(..))
57import Data.Text.Internal.Private (runText)
57import Data.Text.Internal.Private (runText)
@@ -68,7 +68,7 @@ default(Int)
68
68
69-- | /O(n)/ Convert a 'Text' into a 'Stream Char'.
69-- | /O(n)/ Convert a 'Text' into a 'Stream Char'.
70stream :: Text -> Stream Char
70stream :: Text -> Stream Char
71−stream (Text arr off len) = Stream next off (maxSize len)
71+stream (Text arr off len) = Stream next off (betweenSize (len `quot` 2) len)
72 where
72 where
73 !end = off+len
73 !end = off+len
74 next !i
74 next !i
@@ -83,7 +83,7 @@ stream (Text arr off len) = Stream next off (maxSize len)
83-- | /O(n)/ Convert a 'Text' into a 'Stream Char', but iterate
83-- | /O(n)/ Convert a 'Text' into a 'Stream Char', but iterate
84-- backwards.
84-- backwards.
85reverseStream :: Text -> Stream Char
85reverseStream :: Text -> Stream Char
86−reverseStream (Text arr off len) = Stream next (off+len-1) (maxSize len)
86+reverseStream (Text arr off len) = Stream next (off+len-1) (betweenSize (len `quot` 2) len)
87 where
87 where
88 {-# INLINE next #-}
88 {-# INLINE next #-}
89 next !i
89 next !i
Data/Text/Internal/Fusion/Common.hs+3−1
@@ -321,8 +321,10 @@ compareLengthI :: Integral a => Stream Char -> a -> Ordering
321compareLengthI (Stream next s0 len) n =
321compareLengthI (Stream next s0 len) n =
322 case exactly len of
322 case exactly len of
323 Nothing
323 Nothing
324− | upperBound (fromIntegral n) len < (fromIntegral n) -> LT
324+ | upperBound n' len < n' -> LT
325+ | lowerBound n' len > n' -> GT
325 | otherwise -> loop_cmp 0 s0
326 | otherwise -> loop_cmp 0 s0
327+ where n' = fromIntegral n
326 Just i -> compare (fromIntegral i) n
328 Just i -> compare (fromIntegral i) n
327 where
329 where
328 loop_cmp !z s = case next s of
330 loop_cmp !z s = case next s of
Data/Text/Internal/Fusion/Size.hs+50−46
@@ -22,10 +22,12 @@ module Data.Text.Internal.Fusion.Size
22 , exactly
22 , exactly
23 , exactSize
23 , exactSize
24 , maxSize
24 , maxSize
25+ , betweenSize
25 , unknownSize
26 , unknownSize
26 , smaller
27 , smaller
27 , larger
28 , larger
28 , upperBound
29 , upperBound
30+ , lowerBound
29 , isEmpty
31 , isEmpty
30 ) where
32 ) where
31
33
@@ -33,14 +35,13 @@ module Data.Text.Internal.Fusion.Size
33import Control.Exception (assert)
35import Control.Exception (assert)
34#endif
36#endif
35
37
36−data Size = Exact {-# UNPACK #-} !Int -- ^ Exact size.
38+data Size = Between {-# UNPACK #-} !Int {-# UNPACK #-} !Int -- ^ Lower and upper bounds on size.
37− | Max {-# UNPACK #-} !Int -- ^ Upper bound on size.
38− | Unknown -- ^ Unknown size.
39+ | Unknown -- ^ Unknown size.
39 deriving (Eq, Show)
40 deriving (Eq, Show)
40
41
41exactly :: Size -> Maybe Int
42exactly :: Size -> Maybe Int
42−exactly (Exact n) = Just n
43+exactly (Between na nb) | na == nb = Just na
43−exactly _ = Nothing
44+exactly _ = Nothing
44{-# INLINE exactly #-}
45{-# INLINE exactly #-}
45
46
46exactSize :: Int -> Size
47exactSize :: Int -> Size
@@ -48,7 +49,7 @@ exactSize n =
48#if defined(ASSERTS)
49#if defined(ASSERTS)
49 assert (n >= 0)
50 assert (n >= 0)
50#endif
51#endif
51− Exact n
52+ Between n n
52{-# INLINE exactSize #-}
53{-# INLINE exactSize #-}
53
54
54maxSize :: Int -> Size
55maxSize :: Int -> Size
@@ -56,9 +57,18 @@ maxSize n =
56#if defined(ASSERTS)
57#if defined(ASSERTS)
57 assert (n >= 0)
58 assert (n >= 0)
58#endif
59#endif
59− Max n
60+ Between 0 n
60{-# INLINE maxSize #-}
61{-# INLINE maxSize #-}
61
62
63+betweenSize :: Int -> Int -> Size
64+betweenSize m n =
65+#if defined(ASSERTS)
66+ assset (m >= 0)
67+ assert (n >= m)
68+#endif
69+ Between m n
70+{-# INLINE betweenSize #-}
71+
62unknownSize :: Size
72unknownSize :: Size
63unknownSize = Unknown
73unknownSize = Unknown
64{-# INLINE unknownSize #-}
74{-# INLINE unknownSize #-}
@@ -68,7 +78,7 @@ instance Num Size where
68 (-) = subtractSize
78 (-) = subtractSize
69 (*) = mulSize
79 (*) = mulSize
70
80
71− fromInteger = f where f = Exact . fromInteger
81+ fromInteger = f where f = exactSize . fromInteger
72 {-# INLINE f #-}
82 {-# INLINE f #-}
73
83
74add :: Int -> Int -> Int
84add :: Int -> Int -> Int
@@ -78,20 +88,15 @@ add m n | mn >= 0 = mn
78{-# INLINE add #-}
88{-# INLINE add #-}
79
89
80addSize :: Size -> Size -> Size
90addSize :: Size -> Size -> Size
81−addSize (Exact m) (Exact n) = Exact (add m n)
91+addSize (Between ma mb) (Between na nb) = Between (add ma na) (add mb nb)
82−addSize (Exact m) (Max n) = Max (add m n)
83−addSize (Max m) (Exact n) = Max (add m n)
84−addSize (Max m) (Max n) = Max (add m n)
85−addSize _ _ = Unknown
92+addSize _ _ = Unknown
86{-# INLINE addSize #-}
93{-# INLINE addSize #-}
87
94
88subtractSize :: Size -> Size -> Size
95subtractSize :: Size -> Size -> Size
89−subtractSize (Exact m) (Exact n) = Exact (max (m-n) 0)
96+subtractSize (Between ma mb) (Between na nb) = Between (max (ma-nb) 0) (max (mb-na) 0)
90−subtractSize (Exact m) (Max _) = Max m
91−subtractSize (Max m) (Exact n) = Max (max (m-n) 0)
92−subtractSize a@(Max _) (Max _) = a
97+subtractSize a@(Between 0 _) Unknown = a
93−subtractSize a@(Max _) Unknown = a
98+subtractSize (Between _ mb) Unknown = Between 0 mb
94−subtractSize _ _ = Unknown
99+subtractSize _ _ = Unknown
95{-# INLINE subtractSize #-}
100{-# INLINE subtractSize #-}
96
101
97mul :: Int -> Int -> Int
102mul :: Int -> Int -> Int
@@ -101,48 +106,47 @@ mul m n
101{-# INLINE mul #-}
106{-# INLINE mul #-}
102
107
103mulSize :: Size -> Size -> Size
108mulSize :: Size -> Size -> Size
104−mulSize (Exact m) (Exact n) = Exact (mul m n)
109+mulSize (Between ma mb) (Between na nb) = Between (mul ma na) (mul mb nb)
105−mulSize (Exact m) (Max n) = Max (mul m n)
106−mulSize (Max m) (Exact n) = Max (mul m n)
107−mulSize (Max m) (Max n) = Max (mul m n)
108−mulSize _ _ = Unknown
110+mulSize _ _ = Unknown
109{-# INLINE mulSize #-}
111{-# INLINE mulSize #-}
110
112
111-- | Minimum of two size hints.
113-- | Minimum of two size hints.
112smaller :: Size -> Size -> Size
114smaller :: Size -> Size -> Size
113−smaller (Exact m) (Exact n) = Exact (m `min` n)
115+smaller a@(Between ma mb) b@(Between na nb)
114−smaller (Exact m) (Max n) = Max (m `min` n)
116+ | mb <= na = a
115−smaller (Exact m) Unknown = Max m
117+ | nb <= ma = b
116−smaller (Max m) (Exact n) = Max (m `min` n)
118+ | otherwise = Between (ma `min` na) (mb `min` nb)
117−smaller (Max m) (Max n) = Max (m `min` n)
118−smaller a@(Max _) Unknown = a
119+smaller a@(Between 0 _) Unknown = a
119−smaller Unknown (Exact n) = Max n
120+smaller (Between _ mb) Unknown = Between 0 mb
121+smaller Unknown b@(Between 0 _) = b
120−smaller Unknown (Max n) = Max n
122+smaller Unknown (Between _ nb) = Between 0 nb
121−smaller Unknown Unknown = Unknown
123+smaller Unknown Unknown = Unknown
122{-# INLINE smaller #-}
124{-# INLINE smaller #-}
123
125
124-- | Maximum of two size hints.
126-- | Maximum of two size hints.
125larger :: Size -> Size -> Size
127larger :: Size -> Size -> Size
126−larger (Exact m) (Exact n) = Exact (m `max` n)
128+larger a@(Between ma mb) b@(Between na nb)
127−larger a@(Exact m) b@(Max n) | m >= n = a
129+ | ma >= nb = a
128− | otherwise = b
130+ | na >= mb = b
129−larger a@(Max m) b@(Exact n) | n >= m = b
130− | otherwise = a
131+ | otherwise = Between (ma `max` na) (mb `max` nb)
131−larger (Max m) (Max n) = Max (m `max` n)
132−larger _ _ = Unknown
132+larger _ _ = Unknown
133{-# INLINE larger #-}
133{-# INLINE larger #-}
134
134
135-- | Compute the maximum size from a size hint, if possible.
135-- | Compute the maximum size from a size hint, if possible.
136upperBound :: Int -> Size -> Int
136upperBound :: Int -> Size -> Int
137−upperBound _ (Exact n) = n
137+upperBound _ (Between n _) = n
138−upperBound _ (Max n) = n
139−upperBound k _ = k
138+upperBound k _ = k
140{-# INLINE upperBound #-}
139{-# INLINE upperBound #-}
141
140
141+-- | Compute the maximum size from a size hint, if possible.
142+lowerBound :: Int -> Size -> Int
143+lowerBound _ (Between n _) = n
144+lowerBound k _ = k
145+{-# INLINE lowerBound #-}
146+
142isEmpty :: Size -> Bool
147isEmpty :: Size -> Bool
143−isEmpty (Exact n) = n <= 0
148+isEmpty (Between _ n) = n <= 0
144−isEmpty (Max n) = n <= 0
145−isEmpty _ = False
149+isEmpty _ = False
146{-# INLINE isEmpty #-}
150{-# INLINE isEmpty #-}
147
151
148overflowError :: Int
152overflowError :: Int