FenwickTree-0.1: tests/test_Fenwick.hs
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Data.Tree.Fenwick
import Data.List(sort)
import Test.QuickCheck
import Test.QuickCheck.All
tol = 0.001
infix 4 ==~
class AEq a where
(==~) :: a -> a -> Bool
instance AEq Double where
(==~) a b = abs (a - b) <= tol
instance (AEq a, AEq b) => AEq (a, b) where
(a, b) ==~ (c, d) = (a ==~ c) && (b ==~ d)
instance (AEq a) => AEq [a] where
[] ==~ [] = True
(b:bs) ==~ (c:cs) = (b ==~ c) && (bs ==~ cs)
_ ==~ _ = False
instance (AEq a) => AEq (Maybe a) where
Nothing ==~ Nothing = True
(Just f) ==~ (Just g) = f ==~ g
_ ==~ _ = False
emptyFT :: FTree (Double, Double)
emptyFT = empty getFreq cmpFst
getFreq (pos, freq) = freq
cmpFst (pos1, _) (pos2, _) = pos1 `compare` pos2
absFreq (a, freq) = if aFreq == 0.0
then (a, 0.001)
else (a, aFreq)
where
aFreq = abs freq
-- Prepare a list of unique values
uniq [] = []
uniq (e:es) = (e:) . uniq . filter (/= e) $ es
mkTree = foldr insert emptyFT
prop_insert_toList ls = toList (mkTree uls) == sort uls
where
uls = uniq ls
prop_insert_query_non_zero l ls = query l (insert l ft) ==~ snd l + query l ft
where
ft = mkTree $ filter (/=l) ls
prop_freqList ls = toFreqList (mkTree uls) ==~ zip (tail $ scanl (\a b -> snd b + a) 0.0 uls) uls
where
uls = uniq $ sort ls
prop_freqList_query l ls = query l ft ==~ lookupFL l (toFreqList ft)
where
uls = uniq ls
ft = insert l (mkTree uls)
lookupFL a ((f, b):_ ) | a == b = f
lookupFL a ((f, b):cs) = lookupFL a cs
lookupFL a [] = 0.0
-- prop_insert_freqList
prop_toList_fromList ls = toList (fromList cmpFst getFreq uls) == uls
where
uls = sort $ uniq ls
prop_size_fromList ls = size (mkTree uls) == length uls
where
uls = uniq ls
prop_depth_fromList ls = (d <= l) && ((floor . logBase 2 . fromIntegral) l <= d)
where
d = depth (mkTree uls)
l = length uls
uls = uniq ls
prop_freqList_invQuery q ls = ((jf /= Nothing) && (sumFreq > 0)) ==> jf ==~ lookupFreq q (toFreqList ft)
where
jf = invQuery q ft
uls = uniq $ map absFreq ls
ft = mkTree uls
sumFreq = sum $ map snd ls
lookupFreq :: Double -> [(Double, (Double, Double))] -> Maybe (Double, Double)
lookupFreq q ((f, b):_ ) | q <= f = Just b
lookupFreq q ((f, b):cs) | q > f = lookupFreq q cs
lookupFreq q [] = Nothing
main = $quickCheckAll