@@ -22,10 +22,13 @@ module Data.Text.Internal.Fusion.Size
23 , exactSize
23 , exactSize
25 , unknownSize
26 , unknownSize
28 , upperBound
29 , upperBound
@@ -33,14 +36,13 @@ module Data.Text.Internal.Fusion.Size
33import Control.Exception (assert)
36import Control.Exception (assert)
36−data Size = Exact {-# UNPACK #-} !Int -- ^ Exact size.
39+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.
40+ | Unknown -- ^ Unknown size.
39 deriving (Eq, Show)
41 deriving (Eq, Show)
41exactly :: Size -> Maybe Int
43exactly :: Size -> Maybe Int
42−exactly (Exact n) = Just n
44+exactly (Between na nb) | na == nb = Just na
43−exactly _ = Nothing
45+exactly _ = Nothing
44{-# INLINE exactly #-}
46{-# INLINE exactly #-}
46exactSize :: Int -> Size
48exactSize :: Int -> Size
@@ -48,7 +50,7 @@ exactSize n =
48#if defined(ASSERTS)
50#if defined(ASSERTS)
49 assert (n >= 0)
51 assert (n >= 0)
51− Exact n
53+ Between n n
52{-# INLINE exactSize #-}
54{-# INLINE exactSize #-}
54maxSize :: Int -> Size
56maxSize :: Int -> Size
@@ -56,9 +58,18 @@ maxSize n =
56#if defined(ASSERTS)
58#if defined(ASSERTS)
57 assert (n >= 0)
59 assert (n >= 0)
60{-# INLINE maxSize #-}
62{-# INLINE maxSize #-}
64+betweenSize :: Int -> Int -> Size
71+{-# INLINE betweenSize #-}
62unknownSize :: Size
73unknownSize :: Size
63unknownSize = Unknown
74unknownSize = Unknown
64{-# INLINE unknownSize #-}
75{-# INLINE unknownSize #-}
@@ -68,7 +79,7 @@ instance Num Size where
68 (-) = subtractSize
79 (-) = subtractSize
69 (*) = mulSize
80 (*) = mulSize
71− fromInteger = f where f = Exact . fromInteger
82+ fromInteger = f where f = exactSize . fromInteger
72 {-# INLINE f #-}
83 {-# INLINE f #-}
74add :: Int -> Int -> Int
85add :: Int -> Int -> Int
@@ -78,20 +89,15 @@ add m n | mn >= 0 = mn
78{-# INLINE add #-}
89{-# INLINE add #-}
80addSize :: Size -> Size -> Size
91addSize :: Size -> Size -> Size
81−addSize (Exact m) (Exact n) = Exact (add m n)
92+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
93+addSize _ _ = Unknown
86{-# INLINE addSize #-}
94{-# INLINE addSize #-}
88subtractSize :: Size -> Size -> Size
96subtractSize :: Size -> Size -> Size
89−subtractSize (Exact m) (Exact n) = Exact (max (m-n) 0)
97+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
98+subtractSize a@(Between 0 _) Unknown = a
93−subtractSize a@(Max _) Unknown = a
99+subtractSize (Between _ mb) Unknown = Between 0 mb
94−subtractSize _ _ = Unknown
100+subtractSize _ _ = Unknown
95{-# INLINE subtractSize #-}
101{-# INLINE subtractSize #-}
97mul :: Int -> Int -> Int
103mul :: Int -> Int -> Int
@@ -101,48 +107,55 @@ mul m n
101{-# INLINE mul #-}
107{-# INLINE mul #-}
103mulSize :: Size -> Size -> Size
109mulSize :: Size -> Size -> Size
104−mulSize (Exact m) (Exact n) = Exact (mul m n)
110+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
111+mulSize _ _ = Unknown
109{-# INLINE mulSize #-}
112{-# INLINE mulSize #-}
111-- | Minimum of two size hints.
114-- | Minimum of two size hints.
112smaller :: Size -> Size -> Size
115smaller :: Size -> Size -> Size
113−smaller (Exact m) (Exact n) = Exact (m `min` n)
116+smaller a@(Between ma mb) b@(Between na nb)
114−smaller (Exact m) (Max n) = Max (m `min` n)
117+ | mb <= na = a
115−smaller (Exact m) Unknown = Max m
118+ | nb <= ma = b
116−smaller (Max m) (Exact n) = Max (m `min` n)
119+ | otherwise = Between (ma `min` na) (mb `min` nb)
117−smaller (Max m) (Max n) = Max (m `min` n)
118−smaller a@(Max _) Unknown = a
120+smaller a@(Between 0 _) Unknown = a
119−smaller Unknown (Exact n) = Max n
121+smaller (Between _ mb) Unknown = Between 0 mb
122+smaller Unknown b@(Between 0 _) = b
120−smaller Unknown (Max n) = Max n
123+smaller Unknown (Between _ nb) = Between 0 nb
121−smaller Unknown Unknown = Unknown
124+smaller Unknown Unknown = Unknown
122{-# INLINE smaller #-}
125{-# INLINE smaller #-}
124-- | Maximum of two size hints.
127-- | Maximum of two size hints.
125larger :: Size -> Size -> Size
128larger :: Size -> Size -> Size
126−larger (Exact m) (Exact n) = Exact (m `max` n)
129+larger a@(Between ma mb) b@(Between na nb)
127−larger a@(Exact m) b@(Max n) | m >= n = a
130+ | ma >= nb = a
128− | otherwise = b
131+ | na >= mb = b
129−larger a@(Max m) b@(Exact n) | n >= m = b
130− | otherwise = a
132+ | otherwise = Between (ma `max` na) (mb `max` nb)
131−larger (Max m) (Max n) = Max (m `max` n)
132−larger _ _ = Unknown
133+larger _ _ = Unknown
133{-# INLINE larger #-}
134{-# INLINE larger #-}
135-- | Compute the maximum size from a size hint, if possible.
136-- | Compute the maximum size from a size hint, if possible.
136upperBound :: Int -> Size -> Int
137upperBound :: Int -> Size -> Int
137−upperBound _ (Exact n) = n
138+upperBound _ (Between n _) = n
138−upperBound _ (Max n) = n
139−upperBound k _ = k
139+upperBound k _ = k
140{-# INLINE upperBound #-}
140{-# INLINE upperBound #-}
142+-- | Compute the maximum size from a size hint, if possible.
143+lowerBound :: Int -> Size -> Int
144+lowerBound _ (Between n _) = n
146+{-# INLINE lowerBound #-}
148+compareSize :: Size -> Int -> Maybe Ordering
149+compareSize (Between ma mb) n
152+ | ma == n && mb == n = Just EQ
153+compareSize _ _ = Nothing
142isEmpty :: Size -> Bool
156isEmpty :: Size -> Bool
143−isEmpty (Exact n) = n <= 0
157+isEmpty (Between _ n) = n <= 0
144−isEmpty (Max n) = n <= 0
145−isEmpty _ = False
158+isEmpty _ = False
146{-# INLINE isEmpty #-}
159{-# INLINE isEmpty #-}
148overflowError :: Int
161overflowError :: Int