Skip to content

Commit 12b8e48

Browse files
author
Johannes Waldmann
committed
for haskell#470 (does not handle negative keys correctly)
1 parent ee62a3d commit 12b8e48

File tree

1 file changed

+116
-6
lines changed

1 file changed

+116
-6
lines changed

containers-tests/benchmarks/OrdIntSet.hs

Lines changed: 116 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,135 @@
55
module Main where
66

77
import Data.IntSet (IntSet)
8+
import Data.IntSet.Internal
89
import qualified Data.IntSet as IS
910
import Data.IntMap (IntMap)
1011
import qualified Data.IntMap as IM
1112
import qualified Data.Set as S
1213
import qualified Data.Map.Strict as M
1314
import qualified Data.Foldable as F
14-
import Data.List (foldl')
15+
import qualified Data.List
16+
import Data.Bits (shift, complement, (.&.), (.|.), xor, bit, countLeadingZeros)
17+
import Utils.Containers.Internal.BitUtil
1518
import Data.Monoid (Sum(..))
16-
import Control.Monad (guard)
19+
import Control.Monad (guard, forM_)
20+
import Test.LeanCheck
21+
import Test.LeanCheck.Utils.Types (unNat)
1722
import Gauge (bgroup, bench, defaultMain, whnf)
1823

1924
main = do
2025
defaultMain
2126
[ bgroup "det/hard" $ do
2227
n <- [1 .. 20]
2328
return $ bench ("n=" <> show n)
24-
$ whnf (size . det0 2) $ hard_nfa n
29+
$ whnf (IM.size . det0 2) $ hard_nfa n
2530
]
2631

32+
test2 = do
33+
print $ toList (Tip (-1024) 11)
34+
35+
let t1 = fromList [0]
36+
t2@(Bin p m l r) = fromList [-1,0]
37+
print (p,m,l,r)
38+
print $ relate t1 t2
39+
print $ relate t1 l
40+
41+
putStrLn "compare==cis (Tip, Tip)"
42+
checkFor (10^5) $ \ a b -> a == 0 || b == 0 ||
43+
let p = 2^12; q = negate $ 2^12
44+
in compare (Tip p a) (Tip q b) == cis (Tip p a) (Tip q b)
45+
46+
forM_ [0, 2^10, negate $ 2^10 ] $ \ p -> do
47+
putStrLn $ "compare==cis (Tip (" <> show p <> ") *)"
48+
checkFor (10^5) $ \ a b ->
49+
compare (Tip p a) (Tip p b) == cis (Tip p a) (Tip p b)
50+
51+
putStrLn "compare==cis"
52+
checkFor (10^6) $ \ a b -> compare a b == cis a b
53+
54+
instance Listable IntSet where
55+
tiers = mapT (IS.fromList {- . Prelude.map unNat -} ) tiers
56+
57+
-- | detailed outcome of lexicographic comparison of lists.
58+
-- w.r.t. Ordering, there are two extra cases.
59+
data Relation
60+
= Less -- ^ holds for [0,3,4] [0,3,5,1]
61+
| Prefix -- ^ holds for [0,3,4] [0,3,4,5]
62+
| Equals -- ^ holds for [0,3,4] [0,3,4]
63+
| FlipPrefix -- ^ holds for [0,3,4] [0,3]
64+
| Greater -- ^ holds for [0,3,4] [0,2,5]
65+
deriving Show
66+
67+
-- | compare IntSet
68+
cis :: IntSet -> IntSet -> Ordering
69+
cis a b = case relate a b of
70+
Less -> LT
71+
Prefix -> LT
72+
Equals -> EQ
73+
FlipPrefix -> GT
74+
Greater -> GT
75+
76+
relate :: IntSet -> IntSet -> Relation
77+
relate Nil Nil = Equals
78+
relate Nil t2 = Prefix
79+
relate t1 Nil = FlipPrefix
80+
relate (Tip p1 bm1) (Tip p2 bm2) = case compare p1 p2 of
81+
LT -> Less
82+
EQ -> relateBM bm1 bm2
83+
GT -> Greater
84+
relate t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)
85+
| p1 == p2 = combine (relate l1 l2) (relate r1 r2)
86+
| shorter m1 m2 = combine (relate l1 t2) FlipPrefix
87+
| shorter m2 m1 = combine (relate t1 l2) Prefix
88+
| otherwise = case compare p1 p2 of
89+
LT -> Less
90+
GT -> Greater
91+
relate t1@(Bin p1 m1 l1 r1) t2@(Tip p2 bm2)
92+
= combine (relate l1 t2) FlipPrefix
93+
relate t1@(Tip p1 bm1) t2@(Bin p2 m2 l2 r2) = case compare p1 p2 of
94+
LT -> Less
95+
EQ -> combine (relate t1 l2) Prefix
96+
GT -> Greater
97+
98+
combine :: Relation -> Relation -> Relation
99+
combine r eq = case r of
100+
Less -> Less
101+
Prefix -> Greater
102+
Equals -> eq
103+
FlipPrefix -> Less
104+
Greater -> Greater
105+
106+
bmtol m = toList $ Tip 0 m
107+
108+
relateBM :: BitMap -> BitMap -> Relation
109+
relateBM w1 w2 | w1 == w2 = Equals
110+
relateBM w1 w2 = -- e.g., 3=11 1=01
111+
let delta = xor w1 w2 -- 2=10
112+
lowest_diff_mask = delta .&. complement (delta-1) -- 10
113+
prefix = (complement lowest_diff_mask + 1)
114+
.&. (complement lowest_diff_mask) -- 1..100
115+
in if 0 == lowest_diff_mask .&. w1
116+
then if 0 == w1 .&. prefix
117+
then Prefix else Greater
118+
else if 0 == w2 .&. prefix
119+
then FlipPrefix else Less
120+
121+
shorter :: Mask -> Mask -> Bool
122+
shorter m1 m2
123+
= (natFromInt m1) > (natFromInt m2)
124+
{-# INLINE shorter #-}
125+
126+
-- A "Nat" is a natural machine word (an unsigned Int)
127+
type Nat = Word
128+
129+
natFromInt :: Int -> Nat
130+
natFromInt i = fromIntegral i
131+
{-# INLINE natFromInt #-}
132+
133+
intFromNat :: Nat -> Int
134+
intFromNat w = fromIntegral w
135+
{-# INLINE intFromNat #-}
136+
27137

28138
-- evaluate this expression while typing:
29139
-- ghcid -W -Ttest benchmarks/OrdIntSet.hs
@@ -79,7 +189,7 @@ det sigma initial aut =
79189
return (t, s, next)
80190
in go (union_dfa (dfa ts) accu)
81191
(S.insert t done)
82-
(foldl' (\ o (_,_,q) -> S.insert q o) odo ts)
192+
(Data.List.foldl' (\ o (_,_,q) -> S.insert q o) odo ts)
83193
in go IM.empty S.empty $ S.singleton initial
84194

85195

@@ -90,12 +200,12 @@ type Transition = (State, Sigma, State)
90200

91201
nfa :: [Transition ] -> NFA
92202
nfa ts = IM.fromListWith ( IM.unionWith IS.union )
93-
$ map (\(State p,Sigma s,State q) ->
203+
$ Prelude.map (\(State p,Sigma s,State q) ->
94204
(s, IM.singleton p (IS.singleton q))) ts
95205

96206
dfa :: [(IntSet, Sigma, IntSet)] -> DFA
97207
dfa ts = IM.fromListWith ( M.unionWith ( error "WAT") )
98-
$ map (\( p, Sigma s, q) ->
208+
$ Prelude.map (\( p, Sigma s, q) ->
99209
(s, M.singleton p q)) ts
100210

101211
union_dfa a b = IM.unionWith (M.unionWith (error "WAT")) a b

0 commit comments

Comments
 (0)