r-tree-1.0.0.0: test/properties/Test/R2Tree/Double.hs
{-# LANGUAGE RankNTypes #-}
module Test.R2Tree.Double
( test
) where
import qualified Data.R2Tree.Double as R
import Data.R2Tree.Double.Debug
import Data.R2Tree.Double.Unsafe
import No.Tree.D2 (NoTree)
import qualified No.Tree.D2 as No
import Test.Kit
import Test.R2Tree.Double.Sample
import Data.Functor.Identity
import Data.List
import Test.Hspec
mbrT :: Spec
mbrT = do
describe "valid" $ do
it "0 0 1 1" $
validMBR (UnsafeMBR 0 0 1 1) `shouldBe` True
it "1 0 0 1" $
validMBR (UnsafeMBR 1 0 0 1) `shouldBe` False
it "1 1 0 0" $
validMBR (UnsafeMBR 1 1 0 0) `shouldBe` False
describe "union" $ do
it "2 1 3 4 / 6 5 8 9" $
unionMBR (UnsafeMBR 2 1 3 4) (UnsafeMBR 6 5 8 9) `shouldBe` UnsafeMBR 2 1 8 9
it "2 4 5 8 / 1 3 6 9" $
unionMBR (UnsafeMBR 2 4 5 8) (UnsafeMBR 1 3 6 9) `shouldBe` UnsafeMBR 1 3 6 9
it "1 3 6 9 / 2 4 7 8" $
unionMBR (UnsafeMBR 1 3 6 9) (UnsafeMBR 2 4 7 8) `shouldBe` UnsafeMBR 1 3 7 9
describe "area" $ do
it "2 1 8 9" $
areaMBR (UnsafeMBR 2 1 8 9) `shouldBe` 48
it "3 4 6 5" $
areaMBR (UnsafeMBR 3 4 6 5) `shouldBe` 3
describe "margin" $ do
it "2 1 8 9" $
marginMBR (UnsafeMBR 2 1 8 9) `shouldBe` 14
it "3 4 6 5" $
marginMBR (UnsafeMBR 3 4 6 5) `shouldBe` 4
describe "distance" $ do
it "2 1 3 4 / 6 5 8 9" $
distanceMBR (UnsafeMBR 2 1 3 4) (UnsafeMBR 6 5 8 9) `shouldBe` 162
it "2 4 5 8 / 1 3 6 9" $
distanceMBR (UnsafeMBR 2 4 5 8) (UnsafeMBR 1 3 6 9) `shouldBe` 0
it "1 3 6 9 / 2 4 7 8" $
distanceMBR (UnsafeMBR 1 3 6 9) (UnsafeMBR 2 4 7 8) `shouldBe` 4
describe "contains" $ do
it "2 1 3 4 / 6 5 8 9" $
containsMBR (UnsafeMBR 2 1 3 4) (UnsafeMBR 6 5 8 9) `shouldBe` False
it "2 1 8 9 / 3 4 5 6" $
containsMBR (UnsafeMBR 2 1 8 9) (UnsafeMBR 3 4 5 6) `shouldBe` True
it "2 1 8 9 / 2 1 2 8" $
containsMBR (UnsafeMBR 2 1 8 9) (UnsafeMBR 2 1 2 8) `shouldBe` True
it "2 1 8 9 / 8 9 8 9" $
containsMBR (UnsafeMBR 2 1 8 9) (UnsafeMBR 8 9 8 9) `shouldBe` True
describe "contains'" $ do
it "2 1 3 4 / 6 5 8 9" $
containsMBR' (UnsafeMBR 2 1 3 4) (UnsafeMBR 6 5 8 9) `shouldBe` False
it "2 1 8 9 / 3 4 5 6" $
containsMBR' (UnsafeMBR 2 1 8 9) (UnsafeMBR 3 4 5 6) `shouldBe` True
it "2 1 8 9 / 2 1 2 8" $
containsMBR' (UnsafeMBR 2 1 8 9) (UnsafeMBR 2 1 2 8) `shouldBe` False
it "2 1 8 9 / 8 9 8 9" $
containsMBR' (UnsafeMBR 2 1 8 9) (UnsafeMBR 8 9 8 9) `shouldBe` False
describe "intersection" $ do
it "2 1 3 4 / 6 5 8 9" $
intersectionMBR (UnsafeMBR 2 1 3 4) (UnsafeMBR 6 5 8 9) `shouldBe` Nothing
it "1 3 6 9 / 2 4 5 8" $
intersectionMBR (UnsafeMBR 1 3 6 9) (UnsafeMBR 2 4 5 8) `shouldBe` Just (UnsafeMBR 2 4 5 8)
it "2 4 7 8 / 1 3 6 9" $
intersectionMBR (UnsafeMBR 2 4 7 8) (UnsafeMBR 1 3 6 9) `shouldBe` Just (UnsafeMBR 2 4 6 8)
it "1 2 5 4 / 3 4 6 5" $
intersectionMBR (UnsafeMBR 1 2 5 4) (UnsafeMBR 3 4 6 5) `shouldBe` Just (UnsafeMBR 3 4 5 4)
it "3 4 5 6 / 5 6 7 8" $
intersectionMBR (UnsafeMBR 3 4 5 6) (UnsafeMBR 5 6 7 8) `shouldBe` Just (UnsafeMBR 5 6 5 6)
describe "intersection'" $ do
it "2 1 3 4 / 6 5 8 9" $
intersectionMBR' (UnsafeMBR 2 1 3 4) (UnsafeMBR 6 5 8 9) `shouldBe` Nothing
it "1 3 6 9 / 2 4 5 8" $
intersectionMBR' (UnsafeMBR 1 3 6 9) (UnsafeMBR 2 4 5 8) `shouldBe` Just (UnsafeMBR 2 4 5 8)
it "2 4 7 8 / 1 3 6 9" $
intersectionMBR' (UnsafeMBR 2 4 7 8) (UnsafeMBR 1 3 6 9) `shouldBe` Just (UnsafeMBR 2 4 6 8)
it "1 2 5 4 / 3 4 6 5" $
intersectionMBR' (UnsafeMBR 1 2 5 4) (UnsafeMBR 3 4 6 5) `shouldBe` Nothing
it "3 4 5 6 / 5 6 7 8" $
intersectionMBR' (UnsafeMBR 3 4 5 6) (UnsafeMBR 5 6 7 8) `shouldBe` Nothing
predicateT :: Spec
predicateT = do
describe "equals 2 3 7 6" $ do
let Predicate nodePred leafPred = R.equals (UnsafeMBR 2 3 7 6)
it "node 1 2 9 8" $
nodePred (UnsafeMBR 1 2 9 8) `shouldBe` True
it "leaf 1 2 9 8" $
leafPred (UnsafeMBR 1 2 9 8) `shouldBe` False
it "node 2 3 7 6" $
nodePred (UnsafeMBR 2 3 7 6) `shouldBe` True
it "leaf 2 3 7 6" $
leafPred (UnsafeMBR 2 3 7 6) `shouldBe` True
it "node 3 4 6 5" $
nodePred (UnsafeMBR 3 4 6 5) `shouldBe` False
it "leaf 3 4 6 5" $
leafPred (UnsafeMBR 3 4 6 5) `shouldBe` False
it "node 3 4 9 8" $
nodePred (UnsafeMBR 3 4 9 8) `shouldBe` False
it "leaf 3 4 9 8" $
leafPred (UnsafeMBR 3 4 9 8) `shouldBe` False
describe "intersects 2 3 7 6" $ do
let Predicate nodePred leafPred = R.intersects (UnsafeMBR 2 3 7 6)
it "node 1 2 9 8" $
nodePred (UnsafeMBR 1 2 9 8) `shouldBe` True
it "leaf 1 2 9 8" $
leafPred (UnsafeMBR 1 2 9 8) `shouldBe` True
it "node 2 3 7 6" $
nodePred (UnsafeMBR 2 3 7 6) `shouldBe` True
it "leaf 2 3 7 6" $
leafPred (UnsafeMBR 2 3 7 6) `shouldBe` True
it "node 3 4 6 5" $
nodePred (UnsafeMBR 3 4 6 5) `shouldBe` True
it "leaf 3 4 6 5" $
leafPred (UnsafeMBR 3 4 6 5) `shouldBe` True
it "node 3 4 9 8" $
nodePred (UnsafeMBR 3 4 9 8) `shouldBe` True
it "leaf 3 4 9 8" $
leafPred (UnsafeMBR 3 4 9 8) `shouldBe` True
it "node 2 3 7 6" $
nodePred (UnsafeMBR 7 3 8 6) `shouldBe` True
it "leaf 2 3 7 6" $
leafPred (UnsafeMBR 7 3 8 6) `shouldBe` True
describe "intersects' 2 3 7 6" $ do
let Predicate nodePred leafPred = R.intersects' (UnsafeMBR 2 3 7 6)
it "node 2 3 7 6" $
nodePred (UnsafeMBR 7 3 8 6) `shouldBe` False
it "leaf 2 3 7 6" $
leafPred (UnsafeMBR 7 3 8 6) `shouldBe` False
describe "contains 2 3 7 6" $ do
let Predicate nodePred leafPred = R.contains (UnsafeMBR 2 3 7 6)
it "node 1 2 9 8" $
nodePred (UnsafeMBR 1 2 9 8) `shouldBe` True
it "leaf 1 2 9 8" $
leafPred (UnsafeMBR 1 2 9 8) `shouldBe` True
it "node 2 3 7 6" $
nodePred (UnsafeMBR 2 3 7 6) `shouldBe` True
it "leaf 2 3 7 6" $
leafPred (UnsafeMBR 2 3 7 6) `shouldBe` True
it "node 3 4 6 5" $
nodePred (UnsafeMBR 3 4 6 5) `shouldBe` False
it "leaf 3 4 6 5" $
leafPred (UnsafeMBR 3 4 6 5) `shouldBe` False
it "node 3 4 9 8" $
nodePred (UnsafeMBR 3 4 9 8) `shouldBe` False
it "leaf 3 4 9 8" $
leafPred (UnsafeMBR 3 4 9 8) `shouldBe` False
describe "contains' 2 3 7 6" $ do
let Predicate nodePred leafPred = R.contains' (UnsafeMBR 2 3 7 6)
it "node 2 3 7 6" $
nodePred (UnsafeMBR 2 3 7 6) `shouldBe` True
it "leaf 2 3 7 6" $
leafPred (UnsafeMBR 2 3 7 6) `shouldBe` False
describe "containedBy 2 3 7 6" $ do
let Predicate nodePred leafPred = R.containedBy (UnsafeMBR 2 3 7 6)
it "node 1 2 9 8" $
nodePred (UnsafeMBR 1 2 9 8) `shouldBe` True
it "leaf 1 2 9 8" $
leafPred (UnsafeMBR 1 2 9 8) `shouldBe` False
it "node 2 3 7 6" $
nodePred (UnsafeMBR 2 3 7 6) `shouldBe` True
it "leaf 2 3 7 6" $
leafPred (UnsafeMBR 2 3 7 6) `shouldBe` True
it "node 3 4 6 5" $
nodePred (UnsafeMBR 3 4 6 5) `shouldBe` True
it "leaf 3 4 6 5" $
leafPred (UnsafeMBR 3 4 6 5) `shouldBe` True
it "node 3 4 9 8" $
nodePred (UnsafeMBR 3 4 9 8) `shouldBe` True
it "leaf 3 4 9 8" $
leafPred (UnsafeMBR 3 4 9 8) `shouldBe` False
describe "containedBy' 2 3 7 6" $ do
let Predicate nodePred leafPred = R.containedBy' (UnsafeMBR 2 3 7 6)
it "node 2 3 7 6" $
nodePred (UnsafeMBR 2 3 7 6) `shouldBe` True
it "leaf 2 3 7 6" $
leafPred (UnsafeMBR 2 3 7 6) `shouldBe` False
rFromList :: [(MBR, a)] -> R2Tree a
rFromList = foldr (uncurry R.insert) R.empty
rToList :: R2Tree a -> [(MBR, a)]
rToList = R.foldrWithKey (\ba a -> (:) (ba, a)) []
unary0 :: [Case () (R2Tree Int) (NoTree Int)]
unary0 = foldMap (mkUnary0 rFromList) [zero, one, four, five, tiny, small, medium]
unary1 :: [Case (MBR, Int) (R2Tree Int) (NoTree Int)]
unary1 = foldMap (mkUnary1 rFromList) [zero, one, four, five, tiny, small, medium]
unary1_ :: [Case MBR (R2Tree Int) (NoTree Int)]
unary1_ = augment fst unary1
compareMBR :: Ord a => (MBR, a) -> (MBR, a) -> Ordering
compareMBR (MBR x0 y0 x1 y1, a) (MBR x2 y2 x3 y3, b) =
case compare a b of
EQ -> case compare x0 x2 of
EQ -> case compare y0 y2 of
EQ -> case compare x1 x3 of
EQ -> compare y1 y3
cmp -> cmp
cmp -> cmp
cmp -> cmp
cmp -> cmp
type TreeT s a = Test s (R2Tree a) (NoTree a) (R2Tree a) (NoTree a)
treeEq :: Ord a => R2Tree a -> NoTree a -> Bool
treeEq tree no =
case validate tree of
Valid -> sortBy compareMBR (No.toList no) == sortBy compareMBR (rToList tree)
_ -> False
type TreeIdT s a = Test s (R2Tree a) (NoTree a) (Identity (R2Tree a)) (Identity (NoTree a))
treeIdEq :: Ord a => Identity (R2Tree a) -> Identity (NoTree a) -> Bool
treeIdEq (Identity tree) (Identity no) = treeEq tree no
type ListT s a = Test s (R2Tree a) (NoTree a) [a] [a]
listEq :: Ord a => [a] -> [a] -> Bool
listEq as bs = sort as == sort bs
type ListWithKeyT s a = Test s (R2Tree a) (NoTree a) [(MBR, a)] [(MBR, a)]
listWithKeyEq :: Ord a => [(MBR, a)] -> [(MBR, a)] -> Bool
listWithKeyEq as bs = sortBy compareMBR as == sortBy compareMBR bs
insertT :: (Num a, Ord a) => TreeT (MBR, a) a
insertT = Test treeEq (\(bx, x) r -> R.insert bx (negate x) r)
(\(bx, x) no -> No.insert bx (negate x) no)
insertGutT :: (Num a, Ord a) => TreeT (MBR, a) a
insertGutT = Test treeEq (\(bx, x) r -> R.insertGut bx (negate x) r)
(\(bx, x) no -> No.insert bx (negate x) no)
deleteT :: Ord a => TreeT MBR a
deleteT = Test treeEq R.delete No.delete
mapT, mapT' :: TreeT () Int
mapT = mapT_ R.map
mapT' = mapT_ R.map'
mapT_ :: (forall a. (a -> a) -> R2Tree a -> R2Tree a) -> TreeT () Int
mapT_ f = Test treeEq (\_ -> f negate) (\_ -> No.mapWithKey (\_ -> negate))
mapWithKeyT, mapWithKeyT' :: TreeT () Int
mapWithKeyT = mapWithKeyT_ R.mapWithKey
mapWithKeyT' = mapWithKeyT_ R.mapWithKey'
compressMBR :: MBR -> Int
compressMBR (UnsafeMBR xmin ymin xmax ymax) =
truncate xmin + truncate ymin + truncate xmax + truncate ymax
mapWithKeyT_ :: (forall a. (MBR -> a -> a) -> R2Tree a -> R2Tree a) -> TreeT () Int
mapWithKeyT_ f =
let g k i = compressMBR k + i
in Test treeEq (\_ -> f g) (\_ -> No.mapWithKey g)
adjustRangeWithKeyT, adjustRangeWithKeyT' :: (MBR -> Predicate) -> TreeT MBR Int
adjustRangeWithKeyT = adjustRangeWithKeyT_ R.adjustRangeWithKey
adjustRangeWithKeyT' = adjustRangeWithKeyT_ R.adjustRangeWithKey'
adjustRangeWithKeyT_
:: (forall a. Predicate -> (MBR -> a -> a) -> R2Tree a -> R2Tree a)
-> (MBR -> Predicate)
-> TreeT MBR Int
adjustRangeWithKeyT_ f p =
let g k i = compressMBR k + i
in Test treeEq (\bx -> f (p bx) g) (\bx -> No.adjustRangeWithKey (p bx) g)
foldlT, foldrT, foldMapT, foldlT', foldrT' :: ListT () Int
foldlT = foldT $ R.foldl (flip (:)) []
foldrT = foldT $ R.foldr (:) []
foldMapT = foldT $ R.foldMap (:[])
foldlT' = foldT $ R.foldl' (flip (:)) []
foldrT' = foldT $ R.foldr' (:) []
foldT :: (forall a. R2Tree a -> [a]) -> ListT () Int
foldT f = Test listEq (\_ -> f) (\_ -> fmap snd . No.toList)
foldlWithKeyT, foldrWithKeyT, foldMapWithKeyT, foldlWithKeyT', foldrWithKeyT'
:: ListWithKeyT () Int
foldlWithKeyT = foldWithKeyT $ R.foldlWithKey (\z bx x -> (bx, x) : z) []
foldrWithKeyT = foldWithKeyT $ R.foldrWithKey (\bx x -> (:) (bx, x)) []
foldMapWithKeyT = foldWithKeyT $ R.foldMapWithKey (\bx x -> [(bx, x)])
foldlWithKeyT' = foldWithKeyT $ R.foldlWithKey' (\z bx x -> (bx, x) : z) []
foldrWithKeyT' = foldWithKeyT $ R.foldrWithKey' (\bx x -> (:) (bx, x)) []
foldWithKeyT :: (forall a. R2Tree a -> [(MBR, a)]) -> ListWithKeyT () Int
foldWithKeyT f = Test listWithKeyEq (\_ -> f) (\_ -> No.toList)
foldlRangeWithKeyT
, foldrRangeWithKeyT
, foldMapRangeWithKeyT
, foldlRangeWithKeyT'
, foldrRangeWithKeyT'
:: (MBR -> Predicate) -> ListWithKeyT MBR Int
foldlRangeWithKeyT = foldRangeWithKeyT $ \p -> R.foldlRangeWithKey p (\z bx x -> (bx, x) : z) []
foldrRangeWithKeyT = foldRangeWithKeyT $ \p -> R.foldrRangeWithKey p (\bx x -> (:) (bx, x)) []
foldMapRangeWithKeyT = foldRangeWithKeyT $ \p -> R.foldMapRangeWithKey p (\bx x -> [(bx, x)])
foldlRangeWithKeyT' = foldRangeWithKeyT $ \p -> R.foldlRangeWithKey' p (\z bx x -> (bx, x) : z) []
foldrRangeWithKeyT' = foldRangeWithKeyT $ \p -> R.foldrRangeWithKey' p (\bx x -> (:) (bx, x)) []
foldRangeWithKeyT
:: (forall a. Predicate -> R2Tree a -> [(MBR, a)])
-> (MBR -> Predicate) -> ListWithKeyT MBR Int
foldRangeWithKeyT f p =
Test listWithKeyEq (\bx -> f (p bx))
(\bx -> No.foldrRangeWithKey (p bx) (\ba a -> (:) (ba, a)) [])
traverseT :: TreeIdT () Int
traverseT =
let f = Identity . negate
in Test treeIdEq (\_ -> R.traverse f) (\_ -> No.traverseWithKey (\_ -> f))
traverseWithKeyT :: TreeIdT () Int
traverseWithKeyT =
let f k i = Identity $ compressMBR k + i
in Test treeIdEq (\_ -> R.traverseWithKey f) (\_ -> No.traverseWithKey f)
traverseRangeWithKeyT :: (MBR -> Predicate) -> TreeIdT MBR Int
traverseRangeWithKeyT p =
let f k i = Identity $ compressMBR k + i
in Test treeIdEq (\bx -> R.traverseRangeWithKey (p bx) f) (\bx -> No.traverseRangeWithKey (p bx) f)
test :: Spec
test = do
describe "MBR"
mbrT
describe "Predicate"
predicateT
describe "R2Tree" $ do
describe "Single-key" $ do
it "insert" $ run unary1 insertT
it "insertGut" $ run unary1 insertGutT
it "delete" $ run unary1_ deleteT
describe "Range" $ do
it "adjustRangeWithKey/equals" $ run unary1_ (adjustRangeWithKeyT R.equals)
it "adjustRangeWithKey/intersects" $ run unary1_ (adjustRangeWithKeyT R.intersects)
it "adjustRangeWithKey'/equals" $ run unary1_ (adjustRangeWithKeyT' R.equals)
it "adjustRangeWithKey'/intersects" $ run unary1_ (adjustRangeWithKeyT' R.intersects)
it "foldlRangeWithKey/equals" $ run unary1_ (foldlRangeWithKeyT R.equals)
it "foldlRangeWithKey/intersects" $ run unary1_ (foldlRangeWithKeyT R.intersects)
it "foldlRangeWithKey'/equals" $ run unary1_ (foldlRangeWithKeyT' R.equals)
it "foldlRangeWithKey'/intersects" $ run unary1_ (foldlRangeWithKeyT' R.intersects)
it "foldrRangeWithKey/equals" $ run unary1_ (foldrRangeWithKeyT R.equals)
it "foldrRangeWithKey/intersects" $ run unary1_ (foldrRangeWithKeyT R.intersects)
it "foldrRangeWithKey'/equals" $ run unary1_ (foldrRangeWithKeyT' R.equals)
it "foldrRangeWithKey'/intersects" $ run unary1_ (foldrRangeWithKeyT' R.intersects)
it "foldMapRangeWithKey/equals" $ run unary1_ (foldMapRangeWithKeyT R.equals)
it "foldMapRangeWithKey/intersects" $ run unary1_ (foldMapRangeWithKeyT R.intersects)
it "traverseRangeWithKey/equals" $ run unary1_ (traverseRangeWithKeyT R.equals)
it "traverseRangeWithKey/intersects" $ run unary1_ (traverseRangeWithKeyT R.intersects)
describe "Full tree" $ do
it "map" $ run unary0 mapT
it "map'" $ run unary0 mapT'
it "mapWithKey" $ run unary0 mapWithKeyT
it "mapWithKey'" $ run unary0 mapWithKeyT'
it "foldl" $ run unary0 foldlT
it "foldl'" $ run unary0 foldlT'
it "foldlWithKey" $ run unary0 foldlWithKeyT
it "foldlWithKey'" $ run unary0 foldlWithKeyT'
it "foldr" $ run unary0 foldrT
it "foldr'" $ run unary0 foldrT'
it "foldrWithKey" $ run unary0 foldrWithKeyT
it "foldrWithKey'" $ run unary0 foldrWithKeyT'
it "foldMap" $ run unary0 foldMapT
it "foldMapWithKey" $ run unary0 foldMapWithKeyT
it "traverse" $ run unary0 traverseT
it "traverseWithKey" $ run unary0 traverseWithKeyT