Skip to content

Commit bd6bcce

Browse files
committed
Partially revert haskell#670
Bodigrim found a bug in the new `Ord` instance in haskell#783. Put the old one one back. Fixes haskell#783.
1 parent 56331cd commit bd6bcce

File tree

1 file changed

+2
-150
lines changed

1 file changed

+2
-150
lines changed

containers/src/Data/IntSet/Internal.hs

Lines changed: 2 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,156 +1216,8 @@ nequal _ _ = True
12161216
--------------------------------------------------------------------}
12171217

12181218
instance Ord IntSet where
1219-
compare Nil Nil = EQ
1220-
compare Nil _ = LT
1221-
compare _ Nil = GT
1222-
compare t1@(Tip _ _) t2@(Tip _ _)
1223-
= orderingOf $ relateTipTip t1 t2
1224-
compare xs ys
1225-
| (xsNeg, xsNonNeg) <- splitSign xs
1226-
, (ysNeg, ysNonNeg) <- splitSign ys
1227-
= case relate xsNeg ysNeg of
1228-
Less -> LT
1229-
Prefix -> if null xsNonNeg then LT else GT
1230-
Equals -> orderingOf (relate xsNonNeg ysNonNeg)
1231-
FlipPrefix -> if null ysNonNeg then GT else LT
1232-
Greater -> GT
1233-
1234-
-- | detailed outcome of lexicographic comparison of lists.
1235-
-- w.r.t. Ordering, there are two extra cases,
1236-
-- since (++) is not monotonic w.r.t. lex. order on lists
1237-
-- (which is used by definition):
1238-
-- consider comparison of (Bin [0,3,4] [ 6] ) to (Bin [0,3] [7] )
1239-
-- where [0,3,4] > [0,3] but [0,3,4,6] < [0,3,7].
1240-
1241-
data Relation
1242-
= Less -- ^ holds for [0,3,4] [0,3,5,1]
1243-
| Prefix -- ^ holds for [0,3,4] [0,3,4,5]
1244-
| Equals -- ^ holds for [0,3,4] [0,3,4]
1245-
| FlipPrefix -- ^ holds for [0,3,4] [0,3]
1246-
| Greater -- ^ holds for [0,3,4] [0,2,5]
1247-
deriving (Show, Eq)
1248-
1249-
orderingOf :: Relation -> Ordering
1250-
{-# INLINE orderingOf #-}
1251-
orderingOf r = case r of
1252-
Less -> LT
1253-
Prefix -> LT
1254-
Equals -> EQ
1255-
FlipPrefix -> GT
1256-
Greater -> GT
1257-
1258-
-- | precondition: each argument is non-mixed
1259-
relate :: IntSet -> IntSet -> Relation
1260-
relate Nil Nil = Equals
1261-
relate Nil _t2 = Prefix
1262-
relate _t1 Nil = FlipPrefix
1263-
relate t1@Tip{} t2@Tip{} = relateTipTip t1 t2
1264-
relate t1@(Bin _p1 m1 l1 r1) t2@(Bin _p2 m2 l2 r2)
1265-
| succUpperbound t1 <= lowerbound t2 = Less
1266-
| lowerbound t1 >= succUpperbound t2 = Greater
1267-
| otherwise = case compare (natFromInt m1) (natFromInt m2) of
1268-
GT -> combine_left (relate l1 t2)
1269-
EQ -> combine (relate l1 l2) (relate r1 r2)
1270-
LT -> combine_right (relate t1 l2)
1271-
relate t1@(Bin _p1 m1 l1 _r1) t2@(Tip p2 _bm2)
1272-
| succUpperbound t1 <= lowerbound t2 = Less
1273-
| lowerbound t1 >= succUpperbound t2 = Greater
1274-
| 0 == (m1 .&. p2) = combine_left (relate l1 t2)
1275-
| otherwise = Less
1276-
relate t1@(Tip p1 _bm1) t2@(Bin _p2 m2 l2 _r2)
1277-
| succUpperbound t1 <= lowerbound t2 = Less
1278-
| lowerbound t1 >= succUpperbound t2 = Greater
1279-
| 0 == (p1 .&. m2) = combine_right (relate t1 l2)
1280-
| otherwise = Greater
1281-
1282-
relateTipTip :: IntSet -> IntSet -> Relation
1283-
{-# INLINE relateTipTip #-}
1284-
relateTipTip (Tip p1 bm1) (Tip p2 bm2) = case compare p1 p2 of
1285-
LT -> Less
1286-
EQ -> relateBM bm1 bm2
1287-
GT -> Greater
1288-
relateTipTip _ _ = error "relateTipTip"
1289-
1290-
relateBM :: BitMap -> BitMap -> Relation
1291-
{-# inline relateBM #-}
1292-
relateBM w1 w2 | w1 == w2 = Equals
1293-
relateBM w1 w2 =
1294-
let delta = xor w1 w2
1295-
lowest_diff_mask = delta .&. complement (delta-1)
1296-
prefix = (complement lowest_diff_mask + 1)
1297-
.&. (complement lowest_diff_mask)
1298-
in if 0 == lowest_diff_mask .&. w1
1299-
then if 0 == w1 .&. prefix
1300-
then Prefix else Greater
1301-
else if 0 == w2 .&. prefix
1302-
then FlipPrefix else Less
1303-
1304-
-- | This function has the property
1305-
-- relate t1@(Bin p m l1 r1) t2@(Bin p m l2 r2) = combine (relate l1 l2) (relate r1 r2)
1306-
-- It is important that `combine` is lazy in the second argument (achieved by inlining)
1307-
combine :: Relation -> Relation -> Relation
1308-
{-# inline combine #-}
1309-
combine r eq = case r of
1310-
Less -> Less
1311-
Prefix -> Greater
1312-
Equals -> eq
1313-
FlipPrefix -> Less
1314-
Greater -> Greater
1315-
1316-
-- | This function has the property
1317-
-- relate t1@(Bin p1 m1 l1 r1) t2 = combine_left (relate l1 t2)
1318-
-- under the precondition that the range of l1 contains the range of t2,
1319-
-- and r1 is non-empty
1320-
combine_left :: Relation -> Relation
1321-
{-# inline combine_left #-}
1322-
combine_left r = case r of
1323-
Less -> Less
1324-
Prefix -> Greater
1325-
Equals -> FlipPrefix
1326-
FlipPrefix -> FlipPrefix
1327-
Greater -> Greater
1328-
1329-
-- | This function has the property
1330-
-- relate t1 t2@(Bin p2 m2 l2 r2) = combine_right (relate t1 l2)
1331-
-- under the precondition that the range of t1 is included in the range of l2,
1332-
-- and r2 is non-empty
1333-
combine_right :: Relation -> Relation
1334-
{-# inline combine_right #-}
1335-
combine_right r = case r of
1336-
Less -> Less
1337-
Prefix -> Prefix
1338-
Equals -> Prefix
1339-
FlipPrefix -> Less
1340-
Greater -> Greater
1341-
1342-
-- | shall only be applied to non-mixed non-Nil trees
1343-
lowerbound :: IntSet -> Int
1344-
{-# INLINE lowerbound #-}
1345-
lowerbound Nil = error "lowerbound: Nil"
1346-
lowerbound (Tip p _) = p
1347-
lowerbound (Bin p _ _ _) = p
1348-
1349-
-- | this is one more than the actual upper bound (to save one operation)
1350-
-- shall only be applied to non-mixed non-Nil trees
1351-
succUpperbound :: IntSet -> Int
1352-
{-# INLINE succUpperbound #-}
1353-
succUpperbound Nil = error "succUpperbound: Nil"
1354-
succUpperbound (Tip p _) = p + wordSize
1355-
succUpperbound (Bin p m _ _) = p + shiftR m 1
1356-
1357-
-- | split a set into subsets of negative and non-negative elements
1358-
splitSign :: IntSet -> (IntSet,IntSet)
1359-
{-# INLINE splitSign #-}
1360-
splitSign t@(Tip kx _)
1361-
| kx >= 0 = (Nil, t)
1362-
| otherwise = (t, Nil)
1363-
splitSign t@(Bin p m l r)
1364-
-- m < 0 is the usual way to find out if we have positives and negatives (see findMax)
1365-
| m < 0 = (r, l)
1366-
| p < 0 = (t, Nil)
1367-
| otherwise = (Nil, t)
1368-
splitSign Nil = (Nil, Nil)
1219+
compare s1 s2 = compare (toAscList s1) (toAscList s2)
1220+
-- tentative implementation. See if more efficient exists.
13691221

13701222
{--------------------------------------------------------------------
13711223
Show

0 commit comments

Comments
 (0)