Buglet in Data.IntSet.split and Data.IntSet.splitMember, patch included.

Arthur van Leeuwen arthurvl at cs.uu.nl
Thu Oct 27 12:10:52 EDT 2005


Hello mailinglist-members,

on the #haskell IRC channel Ketil Z. Malde noted that Data.IntSet.split
failed on the case

 > let m = 1000000 in Data.IntSet.split (16*m) $ Data.IntSet.fromList  
$ map (*m) [17,18,19,30,40]

so Bertram Felgenhauer (int-e at gmx.de) and I set out to fix that, noting
along the way that Data.IntSet.splitMember was broken as well, and
that negative numbers were not handled correctly either. The following
patch fixes the problems:

----- 8< --- cut here --- >8 -----
--- IntSet.hs    2005-10-27 17:18:15.000000000 +0200
+++ FixedIntSet.hs    2005-10-27 17:59:49.000000000 +0200
@@ -35,7 +35,7 @@
-- (32 or 64).
------------------------------------------------------------------------ 
-----
-module Data.IntSet  (
+module IntSet  (
              -- * Set type
                IntSet          -- instance Eq,Show
@@ -454,8 +454,23 @@
split x t
    = case t of
        Bin p m l r
-        | zero x m  -> let (lt,gt) = split x l in (lt,union gt r)
-        | otherwise -> let (lt,gt) = split x r in (union l lt,gt)
+        | m < 0       -> if x >= 0 then let (lt,gt) = split' x l in  
(union r lt, gt)
+                                   else let (lt,gt) = split' x r in  
(lt, union gt l)
+        | otherwise   -> split' x t
+      Tip y
+        | x>y         -> (t,Nil)
+        | x<y         -> (Nil,t)
+        | otherwise   -> (Nil,Nil)
+      Nil             -> (Nil, Nil)
+
+split' :: Int -> IntSet -> (IntSet,IntSet)
+split' x t
+  = case t of
+      Bin p m l r
+        | match x p m -> if zero x m then let (lt,gt) = split' x l  
in (lt,union gt r)
+                                     else let (lt,gt) = split' x r  
in (union l lt,gt)
+        | otherwise   -> if x < p then (Nil, t)
+                                  else (t, Nil)
        Tip y
          | x>y       -> (t,Nil)
          | x<y       -> (Nil,t)
@@ -468,8 +483,23 @@
splitMember x t
    = case t of
        Bin p m l r
-        | zero x m  -> let (lt,found,gt) = splitMember x l in  
(lt,found,union gt r)
-        | otherwise -> let (lt,found,gt) = splitMember x r in (union  
l lt,found,gt)
+        | m < 0       -> if x >= 0 then let (lt,found,gt) =  
splitMember' x l in (union r lt, found, gt)
+                                   else let (lt,found,gt) =  
splitMember' x r in (lt, found, union gt l)
+        | otherwise   -> splitMember' x t
+      Tip y
+        | x>y       -> (t,False,Nil)
+        | x<y       -> (Nil,False,t)
+        | otherwise -> (Nil,True,Nil)
+      Nil -> (Nil,False,Nil)
+
+splitMember' :: Int -> IntSet -> (IntSet,Bool,IntSet)
+splitMember' x t
+  = case t of
+      Bin p m l r
+         | match x p m ->  if zero x m then let (lt,found,gt) =  
splitMember x l in (lt,found,union gt r)
+                                       else let (lt,found,gt) =  
splitMember x r in (union l lt,found,gt)
+         | otherwise   -> if x < p then (Nil, False, t)
+                                   else (t, False, Nil)
        Tip y
          | x>y       -> (t,False,Nil)
          | x<y       -> (Nil,False,t)
----- 8< --- ereh tuc --- >8 -----

Hope this helps. :)

Doei, Arthur.

-- 
   /\    / |       arthurvl at cs.uu.nl       | Work like you don't need  
the money
/__\  /  | A friend is someone with whom | Love like you have never  
been hurt
/    \/__ | you can dare to be yourself   | Dance like there's nobody  
watching





More information about the Libraries mailing list