From 76ca10fd554f27e5ab14f2f9552a955e85ce842e Mon Sep 17 00:00:00 2001 From: BurningWitness Date: Tue, 3 Sep 2024 14:13:16 +0300 Subject: [PATCH 01/11] Cleanup --- .circleci/config.yml | 4 +- benchmark/space/Main.hs | 2 +- benchmark/time/Main.hs | 16 +- cabal.project | 2 +- data-r-tree.cabal | 97 --------- no/No/Tree/D2.hs | 2 +- src/Data/{RTree/D2 => R2Tree}/Double.hs | 55 +++--- .../D2/Float => R2Tree/Double}/Debug.hs | 12 +- .../{RTree/D2 => R2Tree}/Double/Internal.hs | 184 +++++++++--------- .../D2/Float => R2Tree/Double}/Unsafe.hs | 10 +- src/Data/{RTree/D2 => R2Tree}/Float.hs | 31 ++- .../D2/Double => R2Tree/Float}/Debug.hs | 12 +- .../{RTree/D2 => R2Tree}/Float/Internal.hs | 184 +++++++++--------- .../D2/Double => R2Tree/Float}/Unsafe.hs | 10 +- test/properties/Main.hs | 2 +- .../Test/{RTree/D2 => R2Tree}/Double.hs | 46 ++--- .../{RTree/D2 => R2Tree}/Double/Sample.hs | 4 +- visualizer/Main.hs | 12 +- visualizer/r-tree-visualizer.cabal | 2 +- 19 files changed, 298 insertions(+), 389 deletions(-) delete mode 100644 data-r-tree.cabal rename src/Data/{RTree/D2 => R2Tree}/Double.hs (68%) rename src/Data/{RTree/D2/Float => R2Tree/Double}/Debug.hs (95%) rename src/Data/{RTree/D2 => R2Tree}/Double/Internal.hs (93%) rename src/Data/{RTree/D2/Float => R2Tree/Double}/Unsafe.hs (80%) rename src/Data/{RTree/D2 => R2Tree}/Float.hs (70%) rename src/Data/{RTree/D2/Double => R2Tree/Float}/Debug.hs (95%) rename src/Data/{RTree/D2 => R2Tree}/Float/Internal.hs (93%) rename src/Data/{RTree/D2/Double => R2Tree/Float}/Unsafe.hs (79%) rename test/properties/Test/{RTree/D2 => R2Tree}/Double.hs (92%) rename test/properties/Test/{RTree/D2 => R2Tree}/Double/Sample.hs (97%) diff --git a/.circleci/config.yml b/.circleci/config.yml index dedae93..6f7c690 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ jobs: - checkout - restore_cache: name: Restore - key: linux-<< parameters.version >>-{{ checksum "data-r-tree.cabal" }} + key: linux-<< parameters.version >>-{{ checksum "r-tree.cabal" }} - run: name: Install GHC command: | @@ -28,7 +28,7 @@ jobs: command: cabal new-build --enable-tests --enable-documentation - save_cache: name: Cache - key: linux-<< parameters.version >>-{{ checksum "data-r-tree.cabal" }} + key: linux-<< parameters.version >>-{{ checksum "r-tree.cabal" }} paths: - "/root/.cabal" - "dist-newstyle" diff --git a/benchmark/space/Main.hs b/benchmark/space/Main.hs index 850bf5b..d19518c 100644 --- a/benchmark/space/Main.hs +++ b/benchmark/space/Main.hs @@ -2,7 +2,7 @@ module Main where -import qualified Data.RTree.D2.Float as R +import qualified Data.R2Tree.Float as R import Control.Monad import Data.Foldable diff --git a/benchmark/time/Main.hs b/benchmark/time/Main.hs index 90474c6..c46aeb0 100644 --- a/benchmark/time/Main.hs +++ b/benchmark/time/Main.hs @@ -4,17 +4,17 @@ module Main where -import Data.RTree.D2.Double (RTree, MBR, Predicate) -import qualified Data.RTree.D2.Double as R +import Data.R2Tree.Double (R2Tree, MBR, Predicate) +import qualified Data.R2Tree.Double as R import Control.DeepSeq import Control.Monad import Data.Foldable import Data.List hiding (lookup, map) import Data.Monoid -import Gauge import Prelude hiding (lookup, map) import System.Random.Stateful +import Test.Tasty.Bench @@ -51,7 +51,7 @@ genAreas n = replicateM n . randPoint lookup - :: String -> ([(MBR, Int)] -> RTree Int) + :: String -> ([(MBR, Int)] -> R2Tree Int) -> String -> (MBR -> Predicate) -> Benchmark lookup cat from name pre = env ( do g <- newIOGenM $ mkStdGen 0 @@ -70,7 +70,7 @@ lookup cat from name pre = map - :: String -> ([(MBR, Int)] -> RTree Int) + :: String -> ([(MBR, Int)] -> R2Tree Int) -> String -> (MBR -> Predicate) -> Benchmark map cat from name pre = env ( do g <- newIOGenM $ mkStdGen 0 @@ -83,7 +83,7 @@ map cat from name pre = fmap $ \x -> [R.adjustRangeWithKey (pre x) (\_ -> (+) 1) r] traversal - :: String -> ([(MBR, Int)] -> RTree Int) + :: String -> ([(MBR, Int)] -> R2Tree Int) -> String -> (MBR -> Predicate) -> Benchmark traversal cat from name pre = env ( do g <- newIOGenM $ mkStdGen 0 @@ -96,10 +96,10 @@ traversal cat from name pre = traverse $ \x -> fmap (:[]) $ R.traverseRangeWithKey (pre x) (\_ -> pure @IO . (+) 1) r -fromList :: Foldable t => t (MBR, b) -> RTree b +fromList :: Foldable t => t (MBR, b) -> R2Tree b fromList = foldr (uncurry R.insert) R.empty -fromListGut :: Foldable t => t (MBR, b) -> RTree b +fromListGut :: Foldable t => t (MBR, b) -> R2Tree b fromListGut = foldr (uncurry R.insertGut) R.empty diff --git a/cabal.project b/cabal.project index db3121e..e7c970d 100644 --- a/cabal.project +++ b/cabal.project @@ -1,3 +1,3 @@ packages: - data-r-tree.cabal + r-tree.cabal visualizer/r-tree-visualizer.cabal diff --git a/data-r-tree.cabal b/data-r-tree.cabal deleted file mode 100644 index ad40c5f..0000000 --- a/data-r-tree.cabal +++ /dev/null @@ -1,97 +0,0 @@ -cabal-version: 2.2 - -name: data-r-tree -version: 1.2.0 -synopsis: R/R*-trees. -description: Spatial trees utilizing R-tree and R*-tree algorithms. - -license: MIT -license-file: LICENSE -author: Sebastian Wagner, Birte Wagner, Oleksii Divak -maintainer: Oleksii Divak -copyright: Sebastian Wagner, Birte Wagner, Oleksii Divak -category: Data Structures -build-type: Simple - -extra-doc-files: changelog.md - README.md - -bug-reports: https://github.com/sebastian-philipp/r-tree/issues -homepage: https://github.com/sebastian-philipp/r-tree - -source-repository head - type: git - location: https://github.com/sebastian-philipp/r-tree.git - - - -library - build-depends: base >= 4.12 && < 5 - , deepseq >= 1.4.3 && < 1.6 - - hs-source-dirs: src - - exposed-modules: Data.RTree.D2.Double - Data.RTree.D2.Double.Debug - Data.RTree.D2.Double.Unsafe - Data.RTree.D2.Float - Data.RTree.D2.Float.Debug - Data.RTree.D2.Float.Unsafe - - other-modules: Data.RTree.D2.Double.Internal - Data.RTree.D2.Float.Internal - - ghc-options: -Wall - - default-language: Haskell2010 - -benchmark time - build-depends: base - , data-r-tree - , deepseq - , gauge >= 0.2 && < 0.3 - , random >= 1.2 && < 1.3 - - type: exitcode-stdio-1.0 - - main-is: Main.hs - - ghc-options: -Wall - - hs-source-dirs: benchmark/time - - default-language: Haskell2010 - -benchmark space - build-depends: base - , data-r-tree - , random - , weigh >= 0.0.16 && < 0.1 - - type: exitcode-stdio-1.0 - - main-is: Main.hs - - ghc-options: -Wall - - hs-source-dirs: benchmark/space - - default-language: Haskell2010 - -test-suite properties - build-depends: base - , data-r-tree - , deepseq - , hspec >= 2 && < 2.12 - , random - - type: exitcode-stdio-1.0 - - main-is: Main.hs - - ghc-options: -Wall - - hs-source-dirs: no - , test/properties - - default-language: Haskell2010 diff --git a/no/No/Tree/D2.hs b/no/No/Tree/D2.hs index 346ab2c..4b005a5 100644 --- a/no/No/Tree/D2.hs +++ b/no/No/Tree/D2.hs @@ -8,7 +8,7 @@ module No.Tree.D2 where -import Data.RTree.D2.Double.Unsafe (MBR (..), Predicate (..)) +import Data.R2Tree.Double.Unsafe (MBR (..), Predicate (..)) import Control.DeepSeq import qualified Data.Foldable as Fold diff --git a/src/Data/RTree/D2/Double.hs b/src/Data/R2Tree/Double.hs similarity index 68% rename from src/Data/RTree/D2/Double.hs rename to src/Data/R2Tree/Double.hs index 19eda3b..a04dff2 100644 --- a/src/Data/RTree/D2/Double.hs +++ b/src/Data/R2Tree/Double.hs @@ -1,7 +1,7 @@ {-# LANGUAGE PatternSynonyms #-} {- | - Module : Data.RTree.D2.Double + Module : Data.R2Tree.Double Copyright : Copyright (c) 2015, Birte Wagner, Sebastian Philipp Copyright (c) 2022, Oleksii Divak License : MIT @@ -10,8 +10,7 @@ Stability : experimental Portability: not portable - @'RTree' a@ is a spine-strict two-dimensional spatial tree - from bounding rectangles of type 'Double' to values of type @a@. + @'R2Tree' a@ is a spine-strict two-dimensional spatial tree using 'Double's as keys. R-trees have no notion of element order, as such: @@ -25,7 +24,7 @@ == Laziness - Evaluating the root of the tree (i.e. @(_ :: 'RTree' a)@) to WHNF + Evaluating the root of the tree (i.e. @(_ :: 'R2Tree' a)@) to WHNF evaluates the entire spine of the tree to normal form. Functions do not perform any additional evaluations unless @@ -34,12 +33,25 @@ == Performance Each function's time complexity is provided in the documentation. - + \(n\) refers to the total number of entries in the tree. + Parts of the tree are denoted using subscripts: \(n_L\) refers to the left side, + \(n_R\) to the right side, \(n_I\) to a range (interval), and + \(n_M\) to entries collected with the use of a 'Monoid'. + + == Inlining + + Functions that produce and consume 'Predicate's inline heavily. + To avoid unnecessary code duplication during compilation consider creating + helper functions that apply these functions one to another, e.g. + +@ +listIntersections :: 'MBR' -> 'R2Tree' a -> [('MBR', a)] +listIntersections mbr = foldrRangeWithKey (intersects mbr) (\a b -> (:) (a, b)) [] +@ - \(r\) refers to the time complexity of the chosen 'Predicate' lookup, - ranging from \(\mathcal{O}(\log n)\) (well-balanced) - to \(\mathcal{O}(n)\) (worst-case) depending on tree quality. + N.B. To inline properly functions that consume 'Predicate's + must mention all of the arguments except for the tree. == Implementation @@ -62,9 +74,9 @@ -} -module Data.RTree.D2.Double +module Data.R2Tree.Double ( MBR (MBR) - , RTree + , R2Tree -- * Construct , empty @@ -82,7 +94,6 @@ module Data.RTree.D2.Double , delete -- * Range - -- | NOTE: both 'Predicate's and functions using them inline heavily. , Predicate , equals , intersects @@ -108,47 +119,47 @@ module Data.RTree.D2.Double -- * Full tree -- ** Size - , Data.RTree.D2.Double.Internal.null + , Data.R2Tree.Double.Internal.null , size -- ** Map - , Data.RTree.D2.Double.Internal.map + , Data.R2Tree.Double.Internal.map , map' , mapWithKey , mapWithKey' -- ** Fold -- | === Left-to-right - , Data.RTree.D2.Double.Internal.foldl - , Data.RTree.D2.Double.Internal.foldl' + , Data.R2Tree.Double.Internal.foldl + , Data.R2Tree.Double.Internal.foldl' , foldlWithKey , foldlWithKey' -- | === Right-to-left - , Data.RTree.D2.Double.Internal.foldr - , Data.RTree.D2.Double.Internal.foldr' + , Data.R2Tree.Double.Internal.foldr + , Data.R2Tree.Double.Internal.foldr' , foldrWithKey , foldrWithKey' -- | === Monoid - , Data.RTree.D2.Double.Internal.foldMap + , Data.R2Tree.Double.Internal.foldMap , foldMapWithKey -- ** Traverse - , Data.RTree.D2.Double.Internal.traverse + , Data.R2Tree.Double.Internal.traverse , traverseWithKey ) where -import Data.RTree.D2.Double.Internal +import Data.R2Tree.Double.Internal -- | \(\mathcal{O}(1)\). -- Empty tree. -empty :: RTree a +empty :: R2Tree a empty = Empty -- | \(\mathcal{O}(1)\). -- Tree with a single entry. -singleton :: MBR -> a -> RTree a +singleton :: MBR -> a -> R2Tree a singleton = Leaf1 diff --git a/src/Data/RTree/D2/Float/Debug.hs b/src/Data/R2Tree/Double/Debug.hs similarity index 95% rename from src/Data/RTree/D2/Float/Debug.hs rename to src/Data/R2Tree/Double/Debug.hs index 685e1b8..89a1ee6 100644 --- a/src/Data/RTree/D2/Float/Debug.hs +++ b/src/Data/R2Tree/Double/Debug.hs @@ -1,7 +1,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | - Module : Data.RTree.D2.Float.Debug + Module : Data.R2Tree.Double.Debug Copyright : Copyright (c) 2015, Birte Wagner, Sebastian Philipp Copyright (c) 2022, Oleksii Divak License : MIT @@ -10,11 +10,11 @@ Stability : experimental Portability: not portable - Functions that expose the innerworkings of an 'RTree', but are completely safe + Functions that expose the innerworkings of an 'R2Tree', but are completely safe to use otherwise. -} -module Data.RTree.D2.Float.Debug +module Data.R2Tree.Double.Debug ( showsTree , Validity (..) @@ -22,13 +22,13 @@ module Data.RTree.D2.Float.Debug , validate ) where -import Data.RTree.D2.Float.Internal +import Data.R2Tree.Double.Internal -- | \(\mathcal{O}(n)\). -- Shows the internal structure of the R-tree. -showsTree :: (a -> ShowS) -> RTree a -> ShowS +showsTree :: (a -> ShowS) -> R2Tree a -> ShowS showsTree f = go id 0 where {-# INLINE mbr #-} @@ -139,7 +139,7 @@ carry4 a _ _ _ = a -- | \(\mathcal{O}(n)\). -- Checks whether the tree is well-formed. -validate :: RTree a -> Validity +validate :: R2Tree a -> Validity validate t = case t of Leaf1 _ _ -> Valid diff --git a/src/Data/RTree/D2/Double/Internal.hs b/src/Data/R2Tree/Double/Internal.hs similarity index 93% rename from src/Data/RTree/D2/Double/Internal.hs rename to src/Data/R2Tree/Double/Internal.hs index 3ad9cb1..108765a 100644 --- a/src/Data/RTree/D2/Double/Internal.hs +++ b/src/Data/R2Tree/Double/Internal.hs @@ -4,7 +4,7 @@ , ViewPatterns , UnboxedTuples #-} -module Data.RTree.D2.Double.Internal +module Data.R2Tree.Double.Internal ( MBR (UnsafeMBR, MBR) , validMBR , eqMBR @@ -26,37 +26,37 @@ module Data.RTree.D2.Double.Internal , containedBy , containedBy' - , RTree (..) + , R2Tree (..) - , Data.RTree.D2.Double.Internal.null - , Data.RTree.D2.Double.Internal.size + , Data.R2Tree.Double.Internal.null + , Data.R2Tree.Double.Internal.size - , Data.RTree.D2.Double.Internal.map + , Data.R2Tree.Double.Internal.map , map' , mapWithKey , mapWithKey' , adjustRangeWithKey , adjustRangeWithKey' - , Data.RTree.D2.Double.Internal.foldl - , Data.RTree.D2.Double.Internal.foldl' + , Data.R2Tree.Double.Internal.foldl + , Data.R2Tree.Double.Internal.foldl' , foldlWithKey , foldlWithKey' , foldlRangeWithKey , foldlRangeWithKey' - , Data.RTree.D2.Double.Internal.foldr - , Data.RTree.D2.Double.Internal.foldr' + , Data.R2Tree.Double.Internal.foldr + , Data.R2Tree.Double.Internal.foldr' , foldrWithKey , foldrWithKey' , foldrRangeWithKey , foldrRangeWithKey' - , Data.RTree.D2.Double.Internal.foldMap + , Data.R2Tree.Double.Internal.foldMap , foldMapWithKey , foldMapRangeWithKey - , Data.RTree.D2.Double.Internal.traverse + , Data.R2Tree.Double.Internal.traverse , traverseWithKey , traverseRangeWithKey @@ -269,19 +269,19 @@ containedBy' bx = Predicate (intersectsMBR bx) (containsMBR' bx) -instance Show a => Show (RTree a) where +instance Show a => Show (R2Tree a) where showsPrec = liftShowsPrec showsPrec showList -instance Show1 RTree where +instance Show1 R2Tree where liftShowsPrec showsPrec_ showList_ t r = showParen (t > 10) $ showListWith (liftShowsPrec showsPrec_ showList_ 0) $ foldrWithKey (\k a -> (:) (k, a)) [] r -instance Eq a => Eq (RTree a) where +instance Eq a => Eq (R2Tree a) where (==) = liftEq (==) -instance Eq1 RTree where +instance Eq1 R2Tree where liftEq f = go where {-# INLINE node #-} @@ -338,10 +338,10 @@ instance Eq1 RTree where -instance NFData a => NFData (RTree a) where +instance NFData a => NFData (R2Tree a) where rnf = liftRnf rnf -instance NFData1 RTree where +instance NFData1 R2Tree where liftRnf f = go where go n = @@ -359,35 +359,35 @@ instance NFData1 RTree where --- | Uses 'Data.RTree.D2.Double.Internal.map'. -instance Functor RTree where - fmap = Data.RTree.D2.Double.Internal.map +-- | Uses 'Data.R2Tree.Double.map'. +instance Functor R2Tree where + fmap = Data.R2Tree.Double.Internal.map -instance Foldable RTree where - foldl = Data.RTree.D2.Double.Internal.foldl +instance Foldable R2Tree where + foldl = Data.R2Tree.Double.Internal.foldl - foldr = Data.RTree.D2.Double.Internal.foldr + foldr = Data.R2Tree.Double.Internal.foldr - foldMap = Data.RTree.D2.Double.Internal.foldMap + foldMap = Data.R2Tree.Double.Internal.foldMap - foldl' = Data.RTree.D2.Double.Internal.foldl' + foldl' = Data.R2Tree.Double.Internal.foldl' - foldr' = Data.RTree.D2.Double.Internal.foldr' + foldr' = Data.R2Tree.Double.Internal.foldr' - null = Data.RTree.D2.Double.Internal.null + null = Data.R2Tree.Double.Internal.null length = size -instance Traversable RTree where - traverse = Data.RTree.D2.Double.Internal.traverse +instance Traversable R2Tree where + traverse = Data.R2Tree.Double.Internal.traverse -- | Spine-strict two-dimensional R-tree. -data RTree a = Node2 {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) - | Node3 {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) - | Node4 {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) +data R2Tree a = Node2 {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) + | Node3 {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) + | Node4 {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) | Leaf2 {-# UNPACK #-} !MBR a {-# UNPACK #-} !MBR a | Leaf3 {-# UNPACK #-} !MBR a {-# UNPACK #-} !MBR a {-# UNPACK #-} !MBR a @@ -403,14 +403,14 @@ data RTree a = Node2 {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree -- | \(\mathcal{O}(1)\). -- Check if the tree is empty. -null :: RTree a -> Bool +null :: R2Tree a -> Bool null Empty = True null _ = False -- | \(\mathcal{O}(n)\). -- Calculate the number of elements stored in the tree. -- The returned number is guaranteed to be non-negative. -size :: RTree a -> Int +size :: R2Tree a -> Int size = go where go n = @@ -444,7 +444,7 @@ size = go -- | \(\mathcal{O}(n)\). -- Map a function over all values. -map :: (a -> b) -> RTree a -> RTree b +map :: (a -> b) -> R2Tree a -> R2Tree b map f = go where go n = @@ -474,7 +474,7 @@ map f = go -- | \(\mathcal{O}(n)\). -- Map a function over all values and evaluate the results to WHNF. -map' :: (a -> b) -> RTree a -> RTree b +map' :: (a -> b) -> R2Tree a -> R2Tree b map' f = go where go n = @@ -517,7 +517,7 @@ map' f = go -- | \(\mathcal{O}(n)\). -- Map a function over all t'MBR's and their respective values. -mapWithKey :: (MBR -> a -> b) -> RTree a -> RTree b +mapWithKey :: (MBR -> a -> b) -> R2Tree a -> R2Tree b mapWithKey f = go where go n = @@ -548,7 +548,7 @@ mapWithKey f = go -- | \(\mathcal{O}(n)\). -- Map a function over all t'MBR's and their respective values -- and evaluate the results to WHNF. -mapWithKey' :: (MBR -> a -> b) -> RTree a -> RTree b +mapWithKey' :: (MBR -> a -> b) -> R2Tree a -> R2Tree b mapWithKey' f = go where go n = @@ -591,9 +591,9 @@ mapWithKey' f = go {-# INLINE adjustRangeWithKey #-} --- | \(\mathcal{O}(r + n_{range})\). +-- | \(\mathcal{O}(\log n + n_I)\). -- Map a function over t'MBR's that match the 'Predicate' and their respective values. -adjustRangeWithKey :: Predicate -> (MBR -> a -> a) -> RTree a -> RTree a +adjustRangeWithKey :: Predicate -> (MBR -> a -> a) -> R2Tree a -> R2Tree a adjustRangeWithKey (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -632,10 +632,10 @@ adjustRangeWithKey (Predicate nodePred leafPred) f = go Empty -> Empty {-# INLINE adjustRangeWithKey' #-} --- | \(\mathcal{O}(r + n_{range})\). +-- | \(\mathcal{O}(\log n + n_I)\). -- Map a function over t'MBR's that match the 'Predicate' and their respective values -- and evaluate the results to WHNF. -adjustRangeWithKey' :: Predicate -> (MBR -> a -> a) -> RTree a -> RTree a +adjustRangeWithKey' :: Predicate -> (MBR -> a -> a) -> R2Tree a -> R2Tree a adjustRangeWithKey' (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -689,7 +689,7 @@ adjustRangeWithKey' (Predicate nodePred leafPred) f = go -- | \(\mathcal{O}(n_R)\). -- Fold left-to-right over all values. -foldl :: (b -> a -> b) -> b -> RTree a -> b +foldl :: (b -> a -> b) -> b -> R2Tree a -> b foldl f = go where go z n = @@ -707,7 +707,7 @@ foldl f = go -- | \(\mathcal{O}(n)\). -- Fold left-to-right over all values, applying the operator function strictly. -foldl' :: (b -> a -> b) -> b -> RTree a -> b +foldl' :: (b -> a -> b) -> b -> R2Tree a -> b foldl' f = go where {-# INLINE leaf #-} @@ -729,7 +729,7 @@ foldl' f = go -- | \(\mathcal{O}(n_R)\). -- Fold left-to-right over all t'MBR's and their respective values. -foldlWithKey :: (b -> MBR -> a -> b) -> b -> RTree a -> b +foldlWithKey :: (b -> MBR -> a -> b) -> b -> R2Tree a -> b foldlWithKey f = go where go z n = @@ -748,7 +748,7 @@ foldlWithKey f = go -- | \(\mathcal{O}(n)\). -- Fold left-to-right over all t'MBR's and their respective values, -- applying the operator function strictly. -foldlWithKey' :: (b -> MBR -> a -> b) -> b -> RTree a -> b +foldlWithKey' :: (b -> MBR -> a -> b) -> b -> R2Tree a -> b foldlWithKey' f = go where {-# INLINE leaf #-} @@ -769,10 +769,10 @@ foldlWithKey' f = go {-# INLINE foldlRangeWithKey #-} --- | \(\mathcal{O}(r + n_{{range}_R})\). +-- | \(\mathcal{O}(\log n + n_{I_R})\). -- Fold left-to-right over t'MBR's that match the 'Predicate' -- and their respective values. -foldlRangeWithKey :: Predicate -> (b -> MBR -> a -> b) -> b -> RTree a -> b +foldlRangeWithKey :: Predicate -> (b -> MBR -> a -> b) -> b -> R2Tree a -> b foldlRangeWithKey (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -799,10 +799,10 @@ foldlRangeWithKey (Predicate nodePred leafPred) f = go Empty -> z {-# INLINE foldlRangeWithKey' #-} --- | \(\mathcal{O}(r + n_{range})\). +-- | \(\mathcal{O}(\log n + n_I)\). -- Fold left-to-right over t'MBR's that match the 'Predicate' -- and their respective values, applying the operator function strictly. -foldlRangeWithKey' :: Predicate -> (b -> MBR -> a -> b) -> b -> RTree a -> b +foldlRangeWithKey' :: Predicate -> (b -> MBR -> a -> b) -> b -> R2Tree a -> b foldlRangeWithKey' (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -832,7 +832,7 @@ foldlRangeWithKey' (Predicate nodePred leafPred) f = go -- | \(\mathcal{O}(n_L)\). -- Fold right-to-left over all values. -foldr :: (a -> b -> b) -> b -> RTree a -> b +foldr :: (a -> b -> b) -> b -> R2Tree a -> b foldr f = go where go z n = @@ -850,7 +850,7 @@ foldr f = go -- | \(\mathcal{O}(n)\). -- Fold right-to-left over all values, applying the operator function strictly. -foldr' :: (a -> b -> b) -> b -> RTree a -> b +foldr' :: (a -> b -> b) -> b -> R2Tree a -> b foldr' f = go where {-# INLINE leaf #-} @@ -872,7 +872,7 @@ foldr' f = go -- | \(\mathcal{O}(n_L)\). -- Fold right-to-left over all t'MBR's and their respective values. -foldrWithKey :: (MBR -> a -> b -> b) -> b -> RTree a -> b +foldrWithKey :: (MBR -> a -> b -> b) -> b -> R2Tree a -> b foldrWithKey f = go where go z n = @@ -891,7 +891,7 @@ foldrWithKey f = go -- | \(\mathcal{O}(n)\). -- Fold right-to-left over all t'MBR's and their respective values, -- applying the operator function strictly. -foldrWithKey' :: (MBR -> a -> b -> b) -> b -> RTree a -> b +foldrWithKey' :: (MBR -> a -> b -> b) -> b -> R2Tree a -> b foldrWithKey' f = go where {-# INLINE leaf #-} @@ -912,10 +912,10 @@ foldrWithKey' f = go {-# INLINE foldrRangeWithKey #-} --- | \(\mathcal{O}(r + n_{{range}_L})\). +-- | \(\mathcal{O}(\log n + n_{I_L})\). -- Fold right-to-left over t'MBR's that match the 'Predicate' -- and their respective values. -foldrRangeWithKey :: Predicate -> (MBR -> a -> b -> b) -> b -> RTree a -> b +foldrRangeWithKey :: Predicate -> (MBR -> a -> b -> b) -> b -> R2Tree a -> b foldrRangeWithKey (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -942,10 +942,10 @@ foldrRangeWithKey (Predicate nodePred leafPred) f = go Empty -> z {-# INLINE foldrRangeWithKey' #-} --- | \(\mathcal{O}(r + n_{range})\). +-- | \(\mathcal{O}(\log n + n_I)\). -- Fold right-to-left over t'MBR's that match the 'Predicate' -- and their respective values, applying the operator function strictly. -foldrRangeWithKey' :: Predicate -> (MBR -> a -> b -> b) -> b -> RTree a -> b +foldrRangeWithKey' :: Predicate -> (MBR -> a -> b -> b) -> b -> R2Tree a -> b foldrRangeWithKey' (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -975,7 +975,7 @@ foldrRangeWithKey' (Predicate nodePred leafPred) f = go -- | \(\mathcal{O}(n_M)\). -- Map each value to a monoid and combine the results. -foldMap :: Monoid m => (a -> m) -> RTree a -> m +foldMap :: Monoid m => (a -> m) -> R2Tree a -> m foldMap f = go where go n = @@ -994,7 +994,7 @@ foldMap f = go -- | \(\mathcal{O}(n_M)\). -- Map each t'MBR' and its respective value to a monoid and combine the results. -foldMapWithKey :: Monoid m => (MBR -> a -> m) -> RTree a -> m +foldMapWithKey :: Monoid m => (MBR -> a -> m) -> R2Tree a -> m foldMapWithKey f = go where go n = @@ -1012,10 +1012,10 @@ foldMapWithKey f = go {-# INLINE foldMapRangeWithKey #-} --- | \(\mathcal{O}(r + n_{{range}_M})\). +-- | \(\mathcal{O}(\log n + n_{I_M})\). -- Map each t'MBR' that matches the 'Predicate' and its respective value to a monoid -- and combine the results. -foldMapRangeWithKey :: Monoid m => Predicate -> (MBR -> a -> m) -> RTree a -> m +foldMapRangeWithKey :: Monoid m => Predicate -> (MBR -> a -> m) -> R2Tree a -> m foldMapRangeWithKey (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -1043,11 +1043,10 @@ foldMapRangeWithKey (Predicate nodePred leafPred) f = go -{-# INLINE traverse #-} -- | \(\mathcal{O}(n)\). -- Map each value to an action, evaluate the actions left-to-right and -- collect the results. -traverse :: Applicative f => (a -> f b) -> RTree a -> f (RTree b) +traverse :: Applicative f => (a -> f b) -> R2Tree a -> f (R2Tree b) traverse f = go where go n = @@ -1082,11 +1081,10 @@ traverse f = go Empty -> pure Empty -{-# INLINE traverseWithKey #-} -- | \(\mathcal{O}(n)\). -- Map each t'MBR' and its respective value to an action, -- evaluate the actions left-to-right and collect the results. -traverseWithKey :: Applicative f => (MBR -> a -> f b) -> RTree a -> f (RTree b) +traverseWithKey :: Applicative f => (MBR -> a -> f b) -> R2Tree a -> f (R2Tree b) traverseWithKey f = go where go n = @@ -1122,11 +1120,11 @@ traverseWithKey f = go {-# INLINE traverseRangeWithKey #-} --- | \(\mathcal{O}(r + n_{range})\). +-- | \(\mathcal{O}(\log n + n_I)\). -- Map each t'MBR' that matches the 'Predicate' and its respective value to an action, -- evaluate the actions left-to-right and collect the results. traverseRangeWithKey - :: Applicative f => Predicate -> (MBR -> a -> f a) -> RTree a -> f (RTree a) + :: Applicative f => Predicate -> (MBR -> a -> f a) -> R2Tree a -> f (R2Tree a) traverseRangeWithKey (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -1182,8 +1180,8 @@ union4MBR ba bb bc bd = unionMBR (unionMBR ba bb) (unionMBR bc bd) -data Gut a = GutOne MBR (RTree a) - | GutTwo MBR (RTree a) MBR (RTree a) +data Gut a = GutOne MBR (R2Tree a) + | GutTwo MBR (R2Tree a) MBR (R2Tree a) -- | \(\mathcal{O}(\log n)\). Insert a value into the tree. -- @@ -1191,14 +1189,14 @@ data Gut a = GutOne MBR (RTree a) -- Compared to 'insert' the resulting trees are of lower quality (see the -- [Wikipedia article](https://en.wikipedia.org/w/index.php?title=R*-tree&oldid=1171720351#Performance) -- for a graphic example). -insertGut :: MBR -> a -> RTree a -> RTree a +insertGut :: MBR -> a -> R2Tree a -> R2Tree a insertGut bx x t = case insertGutRoot bx x t of GutOne _ o -> o GutTwo bl l br r -> Node2 bl l br r -insertGutRoot :: MBR -> a -> RTree a -> Gut a +insertGutRoot :: MBR -> a -> R2Tree a -> Gut a insertGutRoot bx x n = case n of Node2 ba a bb b -> @@ -1254,7 +1252,7 @@ insertGutRoot bx x n = GutOne bx (Leaf1 bx x) -insertGut_ :: MBR -> a -> MBR -> RTree a -> Gut a +insertGut_ :: MBR -> a -> MBR -> R2Tree a -> Gut a insertGut_ bx x = go where go bn n = @@ -1313,7 +1311,7 @@ insertGut_ bx x = go -insertGutRootNode :: MBR -> RTree a -> Int -> RTree a -> Gut a +insertGutRootNode :: MBR -> R2Tree a -> Int -> R2Tree a -> Gut a insertGutRootNode bx x depth n = case n of Node2 ba a bb b @@ -1366,11 +1364,11 @@ insertGutRootNode bx x depth n = GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) _ -> assert False - (errorWithoutStackTrace "Data.RTree.D2.Double.Internal.insertGutRootNode: reached a leaf") + (errorWithoutStackTrace "Data.R2Tree.Double.Internal.insertGutRootNode: reached a leaf") n {-# INLINE insertGutNode #-} -insertGutNode :: MBR -> RTree a -> Int -> MBR -> RTree a -> Gut a +insertGutNode :: MBR -> R2Tree a -> Int -> MBR -> R2Tree a -> Gut a insertGutNode bx x = go where go depth bn n = @@ -1425,7 +1423,7 @@ insertGutNode bx x = go GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) _ -> assert False - (errorWithoutStackTrace "Data.RTree.D2.Double.Internal.insertGutNode: reached a leaf") + (errorWithoutStackTrace "Data.R2Tree.Double.Internal.insertGutNode: reached a leaf") n @@ -1621,16 +1619,16 @@ distribute1 q bx x = data Carry a = CarryLeaf MBR a - | CarryNode Int MBR (RTree a) + | CarryNode Int MBR (R2Tree a) -data Ins a = InsOne MBR (RTree a) - | InsCarry Word (Carry a) MBR (RTree a) - | InsTwo Word MBR (RTree a) MBR (RTree a) +data Ins a = InsOne MBR (R2Tree a) + | InsCarry Word (Carry a) MBR (R2Tree a) + | InsTwo Word MBR (R2Tree a) MBR (R2Tree a) -- | \(\mathcal{O}(\log n)\). Insert a value into the tree. -- -- 'insert' uses the R*-tree insertion algorithm. -insert :: MBR -> a -> RTree a -> RTree a +insert :: MBR -> a -> R2Tree a -> R2Tree a insert bx x n = case n of Node2 ba a bb b -> @@ -1705,7 +1703,7 @@ insert bx x n = -insert_ :: Word -> MBR -> a -> Int -> MBR -> RTree a -> Ins a +insert_ :: Word -> MBR -> a -> Int -> MBR -> R2Tree a -> Ins a insert_ mask bx x = go where go height bn n = @@ -1790,7 +1788,7 @@ insert_ mask bx x = go InsOne bx (Leaf1 bx x) -insertNode :: Word -> Int -> MBR -> RTree a -> Int -> MBR -> RTree a -> Ins a +insertNode :: Word -> Int -> MBR -> R2Tree a -> Int -> MBR -> R2Tree a -> Ins a insertNode mask depth bx x = go where go height bn n = @@ -1874,7 +1872,7 @@ insertNode mask depth bx x = go _ -> assert False - (errorWithoutStackTrace "Data.RTree.D2.Double.Internal.insertNode: reached a leaf") + (errorWithoutStackTrace "Data.R2Tree.Double.Internal.insertNode: reached a leaf") n @@ -1975,7 +1973,7 @@ margins (L3 bw _ _ _ _ _ _, L2 bx _ _ _ _, L2 by _ _ _ _, L3 bz _ _ _ _ _ _) = -- If multiple entries qualify, the leftmost one is removed. -- -- 'delete' uses the R-tree deletion algorithm with quadratic-cost splits. -delete :: MBR -> RTree a -> RTree a +delete :: MBR -> R2Tree a -> R2Tree a delete bx s = case delete_ bx 0 s of DelOne _ o -> o @@ -2001,16 +1999,16 @@ delete bx s = ReCons _ _ n re' -> reintegrate (-1) n re' ReLeaf ba a -> Leaf1 ba a -data Re a = ReCons Int MBR (RTree a) (Re a) +data Re a = ReCons Int MBR (R2Tree a) (Re a) | ReLeaf MBR a data Del a = DelNone - | DelOne MBR (RTree a) - | DelSome (Re a) MBR (RTree a) + | DelOne MBR (R2Tree a) + | DelSome (Re a) MBR (R2Tree a) | DelRe (Re a) {-# INLINE delete_ #-} -delete_ :: MBR -> Int -> RTree a -> Del a +delete_ :: MBR -> Int -> R2Tree a -> Del a delete_ bx = go where {-# INLINE cut2 #-} @@ -2146,7 +2144,7 @@ partition1 n_ = go -- | \(\mathcal{O}(n \log n)\). Bulk-load a tree. -- -- 'bulkSTR' uses the Sort-Tile-Recursive algorithm. -bulkSTR :: [(MBR, a)] -> RTree a +bulkSTR :: [(MBR, a)] -> R2Tree a bulkSTR xs = case xs of _:_:_ -> snd $ vertically (length xs) xs @@ -2183,7 +2181,7 @@ bulkSTR xs = compress [] = errorWithoutStackTrace - "Data.RTree.D2.Double.Internal.bulkSTR: zero-sized partition" + "Data.R2Tree.Double.Internal.bulkSTR: zero-sized partition" mend (ba, a) (bb, b) cs = case cs of @@ -2215,4 +2213,4 @@ bulkSTR xs = (unionMBR ba bb, Leaf2 ba a bb b) _ -> errorWithoutStackTrace - "Data.RTree.D2.Double.Internal.bulkSTR: malformed leaf" + "Data.R2Tree.Double.Internal.bulkSTR: malformed leaf" diff --git a/src/Data/RTree/D2/Float/Unsafe.hs b/src/Data/R2Tree/Double/Unsafe.hs similarity index 80% rename from src/Data/RTree/D2/Float/Unsafe.hs rename to src/Data/R2Tree/Double/Unsafe.hs index e3520b1..6d50c1b 100644 --- a/src/Data/RTree/D2/Float/Unsafe.hs +++ b/src/Data/R2Tree/Double/Unsafe.hs @@ -1,7 +1,7 @@ {-# OPTIONS_HADDOCK not-home #-} {- | - Module : Data.RTree.D2.Float.Unsafe + Module : Data.R2Tree.Double.Unsafe Copyright : Copyright (c) 2015, Birte Wagner, Sebastian Philipp Copyright (c) 2022, Oleksii Divak License : MIT @@ -10,10 +10,10 @@ Stability : experimental Portability: not portable - Underlying implementation of the 'RTree'. + Underlying implementation of the 'R2Tree'. -} -module Data.RTree.D2.Float.Unsafe +module Data.R2Tree.Double.Unsafe ( MBR (MBR, UnsafeMBR) -- | === R-tree @@ -22,7 +22,7 @@ module Data.RTree.D2.Float.Unsafe -- -- Invariant: the t'MBR' of each non-leaf node encloses -- all the t'MBR's inside the node. - , RTree (..) + , R2Tree (..) -- * Common operations , validMBR @@ -40,4 +40,4 @@ module Data.RTree.D2.Float.Unsafe , Predicate (..) ) where -import Data.RTree.D2.Float.Internal +import Data.R2Tree.Double.Internal diff --git a/src/Data/RTree/D2/Float.hs b/src/Data/R2Tree/Float.hs similarity index 70% rename from src/Data/RTree/D2/Float.hs rename to src/Data/R2Tree/Float.hs index 0b97335..6953e8a 100644 --- a/src/Data/RTree/D2/Float.hs +++ b/src/Data/R2Tree/Float.hs @@ -1,7 +1,7 @@ {-# LANGUAGE PatternSynonyms #-} {- | - Module : Data.RTree.D2.Float + Module : Data.R2Tree.Float Copyright : Copyright (c) 2015, Birte Wagner, Sebastian Philipp Copyright (c) 2022, Oleksii Divak License : MIT @@ -10,13 +10,13 @@ Stability : experimental Portability: not portable - This module (and every module below it) is a duplicate of "Data.RTree.Double", + This module (and every module below it) is a duplicate of "Data.R2Tree.Double", defined for 'Float's instead of 'Double's. -} -module Data.RTree.D2.Float +module Data.R2Tree.Float ( MBR (MBR) - , RTree + , R2Tree -- * Construct , empty @@ -34,7 +34,6 @@ module Data.RTree.D2.Float , delete -- * Range - -- | NOTE: both 'Predicate's and functions using them inline heavily. , Predicate , equals , intersects @@ -60,47 +59,47 @@ module Data.RTree.D2.Float -- * Full tree -- ** Size - , Data.RTree.D2.Float.Internal.null + , Data.R2Tree.Float.Internal.null , size -- ** Map - , Data.RTree.D2.Float.Internal.map + , Data.R2Tree.Float.Internal.map , map' , mapWithKey , mapWithKey' -- ** Fold -- | === Left-to-right - , Data.RTree.D2.Float.Internal.foldl - , Data.RTree.D2.Float.Internal.foldl' + , Data.R2Tree.Float.Internal.foldl + , Data.R2Tree.Float.Internal.foldl' , foldlWithKey , foldlWithKey' -- | === Right-to-left - , Data.RTree.D2.Float.Internal.foldr - , Data.RTree.D2.Float.Internal.foldr' + , Data.R2Tree.Float.Internal.foldr + , Data.R2Tree.Float.Internal.foldr' , foldrWithKey , foldrWithKey' -- | === Monoid - , Data.RTree.D2.Float.Internal.foldMap + , Data.R2Tree.Float.Internal.foldMap , foldMapWithKey -- ** Traverse - , Data.RTree.D2.Float.Internal.traverse + , Data.R2Tree.Float.Internal.traverse , traverseWithKey ) where -import Data.RTree.D2.Float.Internal +import Data.R2Tree.Float.Internal -- | \(\mathcal{O}(1)\). -- Empty tree. -empty :: RTree a +empty :: R2Tree a empty = Empty -- | \(\mathcal{O}(1)\). -- Tree with a single entry. -singleton :: MBR -> a -> RTree a +singleton :: MBR -> a -> R2Tree a singleton = Leaf1 diff --git a/src/Data/RTree/D2/Double/Debug.hs b/src/Data/R2Tree/Float/Debug.hs similarity index 95% rename from src/Data/RTree/D2/Double/Debug.hs rename to src/Data/R2Tree/Float/Debug.hs index 962f142..40c8629 100644 --- a/src/Data/RTree/D2/Double/Debug.hs +++ b/src/Data/R2Tree/Float/Debug.hs @@ -1,7 +1,7 @@ {-# LANGUAGE ScopedTypeVariables #-} {- | - Module : Data.RTree.D2.Double.Debug + Module : Data.R2Tree.Float.Debug Copyright : Copyright (c) 2015, Birte Wagner, Sebastian Philipp Copyright (c) 2022, Oleksii Divak License : MIT @@ -10,11 +10,11 @@ Stability : experimental Portability: not portable - Functions that expose the innerworkings of an 'RTree', but are completely safe + Functions that expose the innerworkings of an 'R2Tree', but are completely safe to use otherwise. -} -module Data.RTree.D2.Double.Debug +module Data.R2Tree.Float.Debug ( showsTree , Validity (..) @@ -22,13 +22,13 @@ module Data.RTree.D2.Double.Debug , validate ) where -import Data.RTree.D2.Double.Internal +import Data.R2Tree.Float.Internal -- | \(\mathcal{O}(n)\). -- Shows the internal structure of the R-tree. -showsTree :: (a -> ShowS) -> RTree a -> ShowS +showsTree :: (a -> ShowS) -> R2Tree a -> ShowS showsTree f = go id 0 where {-# INLINE mbr #-} @@ -139,7 +139,7 @@ carry4 a _ _ _ = a -- | \(\mathcal{O}(n)\). -- Checks whether the tree is well-formed. -validate :: RTree a -> Validity +validate :: R2Tree a -> Validity validate t = case t of Leaf1 _ _ -> Valid diff --git a/src/Data/RTree/D2/Float/Internal.hs b/src/Data/R2Tree/Float/Internal.hs similarity index 93% rename from src/Data/RTree/D2/Float/Internal.hs rename to src/Data/R2Tree/Float/Internal.hs index 1fae12a..74c63a0 100644 --- a/src/Data/RTree/D2/Float/Internal.hs +++ b/src/Data/R2Tree/Float/Internal.hs @@ -4,7 +4,7 @@ , ViewPatterns , UnboxedTuples #-} -module Data.RTree.D2.Float.Internal +module Data.R2Tree.Float.Internal ( MBR (UnsafeMBR, MBR) , validMBR , eqMBR @@ -26,37 +26,37 @@ module Data.RTree.D2.Float.Internal , containedBy , containedBy' - , RTree (..) + , R2Tree (..) - , Data.RTree.D2.Float.Internal.null - , Data.RTree.D2.Float.Internal.size + , Data.R2Tree.Float.Internal.null + , Data.R2Tree.Float.Internal.size - , Data.RTree.D2.Float.Internal.map + , Data.R2Tree.Float.Internal.map , map' , mapWithKey , mapWithKey' , adjustRangeWithKey , adjustRangeWithKey' - , Data.RTree.D2.Float.Internal.foldl - , Data.RTree.D2.Float.Internal.foldl' + , Data.R2Tree.Float.Internal.foldl + , Data.R2Tree.Float.Internal.foldl' , foldlWithKey , foldlWithKey' , foldlRangeWithKey , foldlRangeWithKey' - , Data.RTree.D2.Float.Internal.foldr - , Data.RTree.D2.Float.Internal.foldr' + , Data.R2Tree.Float.Internal.foldr + , Data.R2Tree.Float.Internal.foldr' , foldrWithKey , foldrWithKey' , foldrRangeWithKey , foldrRangeWithKey' - , Data.RTree.D2.Float.Internal.foldMap + , Data.R2Tree.Float.Internal.foldMap , foldMapWithKey , foldMapRangeWithKey - , Data.RTree.D2.Float.Internal.traverse + , Data.R2Tree.Float.Internal.traverse , traverseWithKey , traverseRangeWithKey @@ -269,19 +269,19 @@ containedBy' bx = Predicate (intersectsMBR bx) (containsMBR' bx) -instance Show a => Show (RTree a) where +instance Show a => Show (R2Tree a) where showsPrec = liftShowsPrec showsPrec showList -instance Show1 RTree where +instance Show1 R2Tree where liftShowsPrec showsPrec_ showList_ t r = showParen (t > 10) $ showListWith (liftShowsPrec showsPrec_ showList_ 0) $ foldrWithKey (\k a -> (:) (k, a)) [] r -instance Eq a => Eq (RTree a) where +instance Eq a => Eq (R2Tree a) where (==) = liftEq (==) -instance Eq1 RTree where +instance Eq1 R2Tree where liftEq f = go where {-# INLINE node #-} @@ -338,10 +338,10 @@ instance Eq1 RTree where -instance NFData a => NFData (RTree a) where +instance NFData a => NFData (R2Tree a) where rnf = liftRnf rnf -instance NFData1 RTree where +instance NFData1 R2Tree where liftRnf f = go where go n = @@ -359,35 +359,35 @@ instance NFData1 RTree where --- | Uses 'Data.RTree.D2.Float.Internal.map'. -instance Functor RTree where - fmap = Data.RTree.D2.Float.Internal.map +-- | Uses 'Data.R2Tree.Float.map'. +instance Functor R2Tree where + fmap = Data.R2Tree.Float.Internal.map -instance Foldable RTree where - foldl = Data.RTree.D2.Float.Internal.foldl +instance Foldable R2Tree where + foldl = Data.R2Tree.Float.Internal.foldl - foldr = Data.RTree.D2.Float.Internal.foldr + foldr = Data.R2Tree.Float.Internal.foldr - foldMap = Data.RTree.D2.Float.Internal.foldMap + foldMap = Data.R2Tree.Float.Internal.foldMap - foldl' = Data.RTree.D2.Float.Internal.foldl' + foldl' = Data.R2Tree.Float.Internal.foldl' - foldr' = Data.RTree.D2.Float.Internal.foldr' + foldr' = Data.R2Tree.Float.Internal.foldr' - null = Data.RTree.D2.Float.Internal.null + null = Data.R2Tree.Float.Internal.null length = size -instance Traversable RTree where - traverse = Data.RTree.D2.Float.Internal.traverse +instance Traversable R2Tree where + traverse = Data.R2Tree.Float.Internal.traverse -- | Spine-strict two-dimensional R-tree. -data RTree a = Node2 {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) - | Node3 {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) - | Node4 {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree a) +data R2Tree a = Node2 {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) + | Node3 {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) + | Node4 {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) {-# UNPACK #-} !MBR !(R2Tree a) | Leaf2 {-# UNPACK #-} !MBR a {-# UNPACK #-} !MBR a | Leaf3 {-# UNPACK #-} !MBR a {-# UNPACK #-} !MBR a {-# UNPACK #-} !MBR a @@ -403,14 +403,14 @@ data RTree a = Node2 {-# UNPACK #-} !MBR !(RTree a) {-# UNPACK #-} !MBR !(RTree -- | \(\mathcal{O}(1)\). -- Check if the tree is empty. -null :: RTree a -> Bool +null :: R2Tree a -> Bool null Empty = True null _ = False -- | \(\mathcal{O}(n)\). -- Calculate the number of elements stored in the tree. -- The returned number is guaranteed to be non-negative. -size :: RTree a -> Int +size :: R2Tree a -> Int size = go where go n = @@ -444,7 +444,7 @@ size = go -- | \(\mathcal{O}(n)\). -- Map a function over all values. -map :: (a -> b) -> RTree a -> RTree b +map :: (a -> b) -> R2Tree a -> R2Tree b map f = go where go n = @@ -474,7 +474,7 @@ map f = go -- | \(\mathcal{O}(n)\). -- Map a function over all values and evaluate the results to WHNF. -map' :: (a -> b) -> RTree a -> RTree b +map' :: (a -> b) -> R2Tree a -> R2Tree b map' f = go where go n = @@ -517,7 +517,7 @@ map' f = go -- | \(\mathcal{O}(n)\). -- Map a function over all t'MBR's and their respective values. -mapWithKey :: (MBR -> a -> b) -> RTree a -> RTree b +mapWithKey :: (MBR -> a -> b) -> R2Tree a -> R2Tree b mapWithKey f = go where go n = @@ -548,7 +548,7 @@ mapWithKey f = go -- | \(\mathcal{O}(n)\). -- Map a function over all t'MBR's and their respective values -- and evaluate the results to WHNF. -mapWithKey' :: (MBR -> a -> b) -> RTree a -> RTree b +mapWithKey' :: (MBR -> a -> b) -> R2Tree a -> R2Tree b mapWithKey' f = go where go n = @@ -591,9 +591,9 @@ mapWithKey' f = go {-# INLINE adjustRangeWithKey #-} --- | \(\mathcal{O}(r + n_{range})\). +-- | \(\mathcal{O}(\log n + n_I)\). -- Map a function over t'MBR's that match the 'Predicate' and their respective values. -adjustRangeWithKey :: Predicate -> (MBR -> a -> a) -> RTree a -> RTree a +adjustRangeWithKey :: Predicate -> (MBR -> a -> a) -> R2Tree a -> R2Tree a adjustRangeWithKey (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -632,10 +632,10 @@ adjustRangeWithKey (Predicate nodePred leafPred) f = go Empty -> Empty {-# INLINE adjustRangeWithKey' #-} --- | \(\mathcal{O}(r + n_{range})\). +-- | \(\mathcal{O}(\log n + n_I)\). -- Map a function over t'MBR's that match the 'Predicate' and their respective values -- and evaluate the results to WHNF. -adjustRangeWithKey' :: Predicate -> (MBR -> a -> a) -> RTree a -> RTree a +adjustRangeWithKey' :: Predicate -> (MBR -> a -> a) -> R2Tree a -> R2Tree a adjustRangeWithKey' (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -689,7 +689,7 @@ adjustRangeWithKey' (Predicate nodePred leafPred) f = go -- | \(\mathcal{O}(n_R)\). -- Fold left-to-right over all values. -foldl :: (b -> a -> b) -> b -> RTree a -> b +foldl :: (b -> a -> b) -> b -> R2Tree a -> b foldl f = go where go z n = @@ -707,7 +707,7 @@ foldl f = go -- | \(\mathcal{O}(n)\). -- Fold left-to-right over all values, applying the operator function strictly. -foldl' :: (b -> a -> b) -> b -> RTree a -> b +foldl' :: (b -> a -> b) -> b -> R2Tree a -> b foldl' f = go where {-# INLINE leaf #-} @@ -729,7 +729,7 @@ foldl' f = go -- | \(\mathcal{O}(n_R)\). -- Fold left-to-right over all t'MBR's and their respective values. -foldlWithKey :: (b -> MBR -> a -> b) -> b -> RTree a -> b +foldlWithKey :: (b -> MBR -> a -> b) -> b -> R2Tree a -> b foldlWithKey f = go where go z n = @@ -748,7 +748,7 @@ foldlWithKey f = go -- | \(\mathcal{O}(n)\). -- Fold left-to-right over all t'MBR's and their respective values, -- applying the operator function strictly. -foldlWithKey' :: (b -> MBR -> a -> b) -> b -> RTree a -> b +foldlWithKey' :: (b -> MBR -> a -> b) -> b -> R2Tree a -> b foldlWithKey' f = go where {-# INLINE leaf #-} @@ -769,10 +769,10 @@ foldlWithKey' f = go {-# INLINE foldlRangeWithKey #-} --- | \(\mathcal{O}(r + n_{{range}_R})\). +-- | \(\mathcal{O}(\log n + n_{I_R})\). -- Fold left-to-right over t'MBR's that match the 'Predicate' -- and their respective values. -foldlRangeWithKey :: Predicate -> (b -> MBR -> a -> b) -> b -> RTree a -> b +foldlRangeWithKey :: Predicate -> (b -> MBR -> a -> b) -> b -> R2Tree a -> b foldlRangeWithKey (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -799,10 +799,10 @@ foldlRangeWithKey (Predicate nodePred leafPred) f = go Empty -> z {-# INLINE foldlRangeWithKey' #-} --- | \(\mathcal{O}(r + n_{range})\). +-- | \(\mathcal{O}(\log n + n_I)\). -- Fold left-to-right over t'MBR's that match the 'Predicate' -- and their respective values, applying the operator function strictly. -foldlRangeWithKey' :: Predicate -> (b -> MBR -> a -> b) -> b -> RTree a -> b +foldlRangeWithKey' :: Predicate -> (b -> MBR -> a -> b) -> b -> R2Tree a -> b foldlRangeWithKey' (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -832,7 +832,7 @@ foldlRangeWithKey' (Predicate nodePred leafPred) f = go -- | \(\mathcal{O}(n_L)\). -- Fold right-to-left over all values. -foldr :: (a -> b -> b) -> b -> RTree a -> b +foldr :: (a -> b -> b) -> b -> R2Tree a -> b foldr f = go where go z n = @@ -850,7 +850,7 @@ foldr f = go -- | \(\mathcal{O}(n)\). -- Fold right-to-left over all values, applying the operator function strictly. -foldr' :: (a -> b -> b) -> b -> RTree a -> b +foldr' :: (a -> b -> b) -> b -> R2Tree a -> b foldr' f = go where {-# INLINE leaf #-} @@ -872,7 +872,7 @@ foldr' f = go -- | \(\mathcal{O}(n_L)\). -- Fold right-to-left over all t'MBR's and their respective values. -foldrWithKey :: (MBR -> a -> b -> b) -> b -> RTree a -> b +foldrWithKey :: (MBR -> a -> b -> b) -> b -> R2Tree a -> b foldrWithKey f = go where go z n = @@ -891,7 +891,7 @@ foldrWithKey f = go -- | \(\mathcal{O}(n)\). -- Fold right-to-left over all t'MBR's and their respective values, -- applying the operator function strictly. -foldrWithKey' :: (MBR -> a -> b -> b) -> b -> RTree a -> b +foldrWithKey' :: (MBR -> a -> b -> b) -> b -> R2Tree a -> b foldrWithKey' f = go where {-# INLINE leaf #-} @@ -912,10 +912,10 @@ foldrWithKey' f = go {-# INLINE foldrRangeWithKey #-} --- | \(\mathcal{O}(r + n_{{range}_L})\). +-- | \(\mathcal{O}(\log n + n_{I_L})\). -- Fold right-to-left over t'MBR's that match the 'Predicate' -- and their respective values. -foldrRangeWithKey :: Predicate -> (MBR -> a -> b -> b) -> b -> RTree a -> b +foldrRangeWithKey :: Predicate -> (MBR -> a -> b -> b) -> b -> R2Tree a -> b foldrRangeWithKey (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -942,10 +942,10 @@ foldrRangeWithKey (Predicate nodePred leafPred) f = go Empty -> z {-# INLINE foldrRangeWithKey' #-} --- | \(\mathcal{O}(r + n_{range})\). +-- | \(\mathcal{O}(\log n + n_I)\). -- Fold right-to-left over t'MBR's that match the 'Predicate' -- and their respective values, applying the operator function strictly. -foldrRangeWithKey' :: Predicate -> (MBR -> a -> b -> b) -> b -> RTree a -> b +foldrRangeWithKey' :: Predicate -> (MBR -> a -> b -> b) -> b -> R2Tree a -> b foldrRangeWithKey' (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -975,7 +975,7 @@ foldrRangeWithKey' (Predicate nodePred leafPred) f = go -- | \(\mathcal{O}(n_M)\). -- Map each value to a monoid and combine the results. -foldMap :: Monoid m => (a -> m) -> RTree a -> m +foldMap :: Monoid m => (a -> m) -> R2Tree a -> m foldMap f = go where go n = @@ -994,7 +994,7 @@ foldMap f = go -- | \(\mathcal{O}(n_M)\). -- Map each t'MBR' and its respective value to a monoid and combine the results. -foldMapWithKey :: Monoid m => (MBR -> a -> m) -> RTree a -> m +foldMapWithKey :: Monoid m => (MBR -> a -> m) -> R2Tree a -> m foldMapWithKey f = go where go n = @@ -1012,10 +1012,10 @@ foldMapWithKey f = go {-# INLINE foldMapRangeWithKey #-} --- | \(\mathcal{O}(r + n_{{range}_M})\). +-- | \(\mathcal{O}(\log n + n_{I_M})\). -- Map each t'MBR' that matches the 'Predicate' and its respective value to a monoid -- and combine the results. -foldMapRangeWithKey :: Monoid m => Predicate -> (MBR -> a -> m) -> RTree a -> m +foldMapRangeWithKey :: Monoid m => Predicate -> (MBR -> a -> m) -> R2Tree a -> m foldMapRangeWithKey (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -1043,11 +1043,10 @@ foldMapRangeWithKey (Predicate nodePred leafPred) f = go -{-# INLINE traverse #-} -- | \(\mathcal{O}(n)\). -- Map each value to an action, evaluate the actions left-to-right and -- collect the results. -traverse :: Applicative f => (a -> f b) -> RTree a -> f (RTree b) +traverse :: Applicative f => (a -> f b) -> R2Tree a -> f (R2Tree b) traverse f = go where go n = @@ -1082,11 +1081,10 @@ traverse f = go Empty -> pure Empty -{-# INLINE traverseWithKey #-} -- | \(\mathcal{O}(n)\). -- Map each t'MBR' and its respective value to an action, -- evaluate the actions left-to-right and collect the results. -traverseWithKey :: Applicative f => (MBR -> a -> f b) -> RTree a -> f (RTree b) +traverseWithKey :: Applicative f => (MBR -> a -> f b) -> R2Tree a -> f (R2Tree b) traverseWithKey f = go where go n = @@ -1122,11 +1120,11 @@ traverseWithKey f = go {-# INLINE traverseRangeWithKey #-} --- | \(\mathcal{O}(r + n_{range})\). +-- | \(\mathcal{O}(\log n + n_I)\). -- Map each t'MBR' that matches the 'Predicate' and its respective value to an action, -- evaluate the actions left-to-right and collect the results. traverseRangeWithKey - :: Applicative f => Predicate -> (MBR -> a -> f a) -> RTree a -> f (RTree a) + :: Applicative f => Predicate -> (MBR -> a -> f a) -> R2Tree a -> f (R2Tree a) traverseRangeWithKey (Predicate nodePred leafPred) f = go where {-# INLINE node #-} @@ -1182,8 +1180,8 @@ union4MBR ba bb bc bd = unionMBR (unionMBR ba bb) (unionMBR bc bd) -data Gut a = GutOne MBR (RTree a) - | GutTwo MBR (RTree a) MBR (RTree a) +data Gut a = GutOne MBR (R2Tree a) + | GutTwo MBR (R2Tree a) MBR (R2Tree a) -- | \(\mathcal{O}(\log n)\). Insert a value into the tree. -- @@ -1191,14 +1189,14 @@ data Gut a = GutOne MBR (RTree a) -- Compared to 'insert' the resulting trees are of lower quality (see the -- [Wikipedia article](https://en.wikipedia.org/w/index.php?title=R*-tree&oldid=1171720351#Performance) -- for a graphic example). -insertGut :: MBR -> a -> RTree a -> RTree a +insertGut :: MBR -> a -> R2Tree a -> R2Tree a insertGut bx x t = case insertGutRoot bx x t of GutOne _ o -> o GutTwo bl l br r -> Node2 bl l br r -insertGutRoot :: MBR -> a -> RTree a -> Gut a +insertGutRoot :: MBR -> a -> R2Tree a -> Gut a insertGutRoot bx x n = case n of Node2 ba a bb b -> @@ -1254,7 +1252,7 @@ insertGutRoot bx x n = GutOne bx (Leaf1 bx x) -insertGut_ :: MBR -> a -> MBR -> RTree a -> Gut a +insertGut_ :: MBR -> a -> MBR -> R2Tree a -> Gut a insertGut_ bx x = go where go bn n = @@ -1313,7 +1311,7 @@ insertGut_ bx x = go -insertGutRootNode :: MBR -> RTree a -> Int -> RTree a -> Gut a +insertGutRootNode :: MBR -> R2Tree a -> Int -> R2Tree a -> Gut a insertGutRootNode bx x depth n = case n of Node2 ba a bb b @@ -1366,11 +1364,11 @@ insertGutRootNode bx x depth n = GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) _ -> assert False - (errorWithoutStackTrace "Data.RTree.D2.Float.Internal.insertGutRootNode: reached a leaf") + (errorWithoutStackTrace "Data.R2Tree.Float.Internal.insertGutRootNode: reached a leaf") n {-# INLINE insertGutNode #-} -insertGutNode :: MBR -> RTree a -> Int -> MBR -> RTree a -> Gut a +insertGutNode :: MBR -> R2Tree a -> Int -> MBR -> R2Tree a -> Gut a insertGutNode bx x = go where go depth bn n = @@ -1425,7 +1423,7 @@ insertGutNode bx x = go GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) _ -> assert False - (errorWithoutStackTrace "Data.RTree.D2.Float.Internal.insertGutNode: reached a leaf") + (errorWithoutStackTrace "Data.R2Tree.Float.Internal.insertGutNode: reached a leaf") n @@ -1621,16 +1619,16 @@ distribute1 q bx x = data Carry a = CarryLeaf MBR a - | CarryNode Int MBR (RTree a) + | CarryNode Int MBR (R2Tree a) -data Ins a = InsOne MBR (RTree a) - | InsCarry Word (Carry a) MBR (RTree a) - | InsTwo Word MBR (RTree a) MBR (RTree a) +data Ins a = InsOne MBR (R2Tree a) + | InsCarry Word (Carry a) MBR (R2Tree a) + | InsTwo Word MBR (R2Tree a) MBR (R2Tree a) -- | \(\mathcal{O}(\log n)\). Insert a value into the tree. -- -- 'insert' uses the R*-tree insertion algorithm. -insert :: MBR -> a -> RTree a -> RTree a +insert :: MBR -> a -> R2Tree a -> R2Tree a insert bx x n = case n of Node2 ba a bb b -> @@ -1705,7 +1703,7 @@ insert bx x n = -insert_ :: Word -> MBR -> a -> Int -> MBR -> RTree a -> Ins a +insert_ :: Word -> MBR -> a -> Int -> MBR -> R2Tree a -> Ins a insert_ mask bx x = go where go height bn n = @@ -1790,7 +1788,7 @@ insert_ mask bx x = go InsOne bx (Leaf1 bx x) -insertNode :: Word -> Int -> MBR -> RTree a -> Int -> MBR -> RTree a -> Ins a +insertNode :: Word -> Int -> MBR -> R2Tree a -> Int -> MBR -> R2Tree a -> Ins a insertNode mask depth bx x = go where go height bn n = @@ -1874,7 +1872,7 @@ insertNode mask depth bx x = go _ -> assert False - (errorWithoutStackTrace "Data.RTree.D2.Float.Internal.insertNode: reached a leaf") + (errorWithoutStackTrace "Data.R2Tree.Float.Internal.insertNode: reached a leaf") n @@ -1975,7 +1973,7 @@ margins (L3 bw _ _ _ _ _ _, L2 bx _ _ _ _, L2 by _ _ _ _, L3 bz _ _ _ _ _ _) = -- If multiple entries qualify, the leftmost one is removed. -- -- 'delete' uses the R-tree deletion algorithm with quadratic-cost splits. -delete :: MBR -> RTree a -> RTree a +delete :: MBR -> R2Tree a -> R2Tree a delete bx s = case delete_ bx 0 s of DelOne _ o -> o @@ -2001,16 +1999,16 @@ delete bx s = ReCons _ _ n re' -> reintegrate (-1) n re' ReLeaf ba a -> Leaf1 ba a -data Re a = ReCons Int MBR (RTree a) (Re a) +data Re a = ReCons Int MBR (R2Tree a) (Re a) | ReLeaf MBR a data Del a = DelNone - | DelOne MBR (RTree a) - | DelSome (Re a) MBR (RTree a) + | DelOne MBR (R2Tree a) + | DelSome (Re a) MBR (R2Tree a) | DelRe (Re a) {-# INLINE delete_ #-} -delete_ :: MBR -> Int -> RTree a -> Del a +delete_ :: MBR -> Int -> R2Tree a -> Del a delete_ bx = go where {-# INLINE cut2 #-} @@ -2146,7 +2144,7 @@ partition1 n_ = go -- | \(\mathcal{O}(n \log n)\). Bulk-load a tree. -- -- 'bulkSTR' uses the Sort-Tile-Recursive algorithm. -bulkSTR :: [(MBR, a)] -> RTree a +bulkSTR :: [(MBR, a)] -> R2Tree a bulkSTR xs = case xs of _:_:_ -> snd $ vertically (length xs) xs @@ -2183,7 +2181,7 @@ bulkSTR xs = compress [] = errorWithoutStackTrace - "Data.RTree.D2.Float.Internal.bulkSTR: zero-sized partition" + "Data.R2Tree.Float.Internal.bulkSTR: zero-sized partition" mend (ba, a) (bb, b) cs = case cs of @@ -2215,4 +2213,4 @@ bulkSTR xs = (unionMBR ba bb, Leaf2 ba a bb b) _ -> errorWithoutStackTrace - "Data.RTree.D2.Float.Internal.bulkSTR: malformed leaf" + "Data.R2Tree.Float.Internal.bulkSTR: malformed leaf" diff --git a/src/Data/RTree/D2/Double/Unsafe.hs b/src/Data/R2Tree/Float/Unsafe.hs similarity index 79% rename from src/Data/RTree/D2/Double/Unsafe.hs rename to src/Data/R2Tree/Float/Unsafe.hs index 41da9d4..28372cb 100644 --- a/src/Data/RTree/D2/Double/Unsafe.hs +++ b/src/Data/R2Tree/Float/Unsafe.hs @@ -1,7 +1,7 @@ {-# OPTIONS_HADDOCK not-home #-} {- | - Module : Data.RTree.D2.Double.Unsafe + Module : Data.R2Tree.Float.Unsafe Copyright : Copyright (c) 2015, Birte Wagner, Sebastian Philipp Copyright (c) 2022, Oleksii Divak License : MIT @@ -10,10 +10,10 @@ Stability : experimental Portability: not portable - Underlying implementation of the 'RTree'. + Underlying implementation of the 'R2Tree'. -} -module Data.RTree.D2.Double.Unsafe +module Data.R2Tree.Float.Unsafe ( MBR (MBR, UnsafeMBR) -- | === R-tree @@ -22,7 +22,7 @@ module Data.RTree.D2.Double.Unsafe -- -- Invariant: the t'MBR' of each non-leaf node encloses -- all the t'MBR's inside the node. - , RTree (..) + , R2Tree (..) -- * Common operations , validMBR @@ -40,4 +40,4 @@ module Data.RTree.D2.Double.Unsafe , Predicate (..) ) where -import Data.RTree.D2.Double.Internal +import Data.R2Tree.Float.Internal diff --git a/test/properties/Main.hs b/test/properties/Main.hs index 4b66fc0..9c94b5d 100644 --- a/test/properties/Main.hs +++ b/test/properties/Main.hs @@ -1,6 +1,6 @@ module Main where -import qualified Test.RTree.D2.Double as R2 +import qualified Test.R2Tree.Double as R2 import Test.Hspec diff --git a/test/properties/Test/RTree/D2/Double.hs b/test/properties/Test/R2Tree/Double.hs similarity index 92% rename from test/properties/Test/RTree/D2/Double.hs rename to test/properties/Test/R2Tree/Double.hs index cb939ee..de6cae2 100644 --- a/test/properties/Test/RTree/D2/Double.hs +++ b/test/properties/Test/R2Tree/Double.hs @@ -1,16 +1,16 @@ {-# LANGUAGE RankNTypes #-} -module Test.RTree.D2.Double +module Test.R2Tree.Double ( test ) where -import qualified Data.RTree.D2.Double as R -import Data.RTree.D2.Double.Debug -import Data.RTree.D2.Double.Unsafe +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.RTree.D2.Double.Sample +import Test.R2Tree.Double.Sample import Data.Functor.Identity import Data.List @@ -262,21 +262,21 @@ predicateT = do -rFromList :: [(MBR, a)] -> RTree a +rFromList :: [(MBR, a)] -> R2Tree a rFromList = foldr (uncurry R.insert) R.empty -rToList :: RTree a -> [(MBR, a)] +rToList :: R2Tree a -> [(MBR, a)] rToList = R.foldrWithKey (\ba a -> (:) (ba, a)) [] -unary0 :: [Case () (RTree Int) (NoTree Int)] +unary0 :: [Case () (R2Tree Int) (NoTree Int)] unary0 = foldMap (mkUnary0 rFromList) [zero, one, four, five, tiny, small, medium] -unary1 :: [Case (MBR, Int) (RTree Int) (NoTree Int)] +unary1 :: [Case (MBR, Int) (R2Tree Int) (NoTree Int)] unary1 = foldMap (mkUnary1 rFromList) [zero, one, four, five, tiny, small, medium] -unary1_ :: [Case MBR (RTree Int) (NoTree Int)] +unary1_ :: [Case MBR (R2Tree Int) (NoTree Int)] unary1_ = augment fst unary1 @@ -293,27 +293,27 @@ compareMBR (MBR x0 y0 x1 y1, a) (MBR x2 y2 x3 y3, b) = cmp -> cmp cmp -> cmp -type TreeT s a = Test s (RTree a) (NoTree a) (RTree a) (NoTree a) +type TreeT s a = Test s (R2Tree a) (NoTree a) (R2Tree a) (NoTree a) -treeEq :: Ord a => RTree a -> NoTree a -> Bool +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 (RTree a) (NoTree a) (Identity (RTree a)) (Identity (NoTree a)) +type TreeIdT s a = Test s (R2Tree a) (NoTree a) (Identity (R2Tree a)) (Identity (NoTree a)) -treeIdEq :: Ord a => Identity (RTree a) -> Identity (NoTree a) -> Bool +treeIdEq :: Ord a => Identity (R2Tree a) -> Identity (NoTree a) -> Bool treeIdEq (Identity tree) (Identity no) = treeEq tree no -type ListT s a = Test s (RTree a) (NoTree a) [a] [a] +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 (RTree a) (NoTree a) [(MBR, a)] [(MBR, a)] +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 @@ -337,7 +337,7 @@ mapT, mapT' :: TreeT () Int mapT = mapT_ R.map mapT' = mapT_ R.map' -mapT_ :: (forall a. (a -> a) -> RTree a -> RTree a) -> TreeT () Int +mapT_ :: (forall a. (a -> a) -> R2Tree a -> R2Tree a) -> TreeT () Int mapT_ f = Test treeEq (\_ -> f negate) (\_ -> No.mapWithKey (\_ -> negate)) @@ -350,7 +350,7 @@ compressMBR :: MBR -> Int compressMBR (UnsafeMBR xmin ymin xmax ymax) = truncate xmin + truncate ymin + truncate xmax + truncate ymax -mapWithKeyT_ :: (forall a. (MBR -> a -> a) -> RTree a -> RTree a) -> TreeT () Int +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) @@ -362,7 +362,7 @@ adjustRangeWithKeyT = adjustRangeWithKeyT_ R.adjustRangeWithKey adjustRangeWithKeyT' = adjustRangeWithKeyT_ R.adjustRangeWithKey' adjustRangeWithKeyT_ - :: (forall a. Predicate -> (MBR -> a -> a) -> RTree a -> RTree a) + :: (forall a. Predicate -> (MBR -> a -> a) -> R2Tree a -> R2Tree a) -> (MBR -> Predicate) -> TreeT MBR Int adjustRangeWithKeyT_ f p = @@ -378,7 +378,7 @@ foldMapT = foldT $ R.foldMap (:[]) foldlT' = foldT $ R.foldl' (flip (:)) [] foldrT' = foldT $ R.foldr' (:) [] -foldT :: (forall a. RTree a -> [a]) -> ListT () Int +foldT :: (forall a. R2Tree a -> [a]) -> ListT () Int foldT f = Test listEq (\_ -> f) (\_ -> fmap snd . No.toList) @@ -391,7 +391,7 @@ 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. RTree a -> [(MBR, a)]) -> ListWithKeyT () Int +foldWithKeyT :: (forall a. R2Tree a -> [(MBR, a)]) -> ListWithKeyT () Int foldWithKeyT f = Test listWithKeyEq (\_ -> f) (\_ -> No.toList) @@ -409,7 +409,7 @@ foldlRangeWithKeyT' = foldRangeWithKeyT $ \p -> R.foldlRangeWithKey' p (\z bx x foldrRangeWithKeyT' = foldRangeWithKeyT $ \p -> R.foldrRangeWithKey' p (\bx x -> (:) (bx, x)) [] foldRangeWithKeyT - :: (forall a. Predicate -> RTree a -> [(MBR, a)]) + :: (forall a. Predicate -> R2Tree a -> [(MBR, a)]) -> (MBR -> Predicate) -> ListWithKeyT MBR Int foldRangeWithKeyT f p = Test listWithKeyEq (\bx -> f (p bx)) @@ -442,7 +442,7 @@ test = do describe "Predicate" predicateT - describe "RTree" $ do + describe "R2Tree" $ do describe "Single-key" $ do it "insert" $ run unary1 insertT it "insertGut" $ run unary1 insertGutT diff --git a/test/properties/Test/RTree/D2/Double/Sample.hs b/test/properties/Test/R2Tree/Double/Sample.hs similarity index 97% rename from test/properties/Test/RTree/D2/Double/Sample.hs rename to test/properties/Test/R2Tree/Double/Sample.hs index 1fc0f42..19a2e03 100644 --- a/test/properties/Test/RTree/D2/Double/Sample.hs +++ b/test/properties/Test/R2Tree/Double/Sample.hs @@ -1,6 +1,6 @@ {-# LANGUAGE RankNTypes #-} -module Test.RTree.D2.Double.Sample +module Test.R2Tree.Double.Sample ( Sample , zero , one @@ -15,7 +15,7 @@ module Test.RTree.D2.Double.Sample , mkUnary1 ) where -import Data.RTree.D2.Double +import Data.R2Tree.Double import No.Tree.D2 (NoTree) import qualified No.Tree.D2 as No import Test.Kit diff --git a/visualizer/Main.hs b/visualizer/Main.hs index 3fb14af..63f3f3b 100644 --- a/visualizer/Main.hs +++ b/visualizer/Main.hs @@ -19,9 +19,9 @@ module Main where -import Data.RTree.D2.Double (RTree, MBR) -import qualified Data.RTree.D2.Double as R -import qualified Data.RTree.D2.Double.Unsafe as R +import Data.R2Tree.Double (R2Tree, MBR) +import qualified Data.R2Tree.Double as R +import qualified Data.R2Tree.Double.Unsafe as R import Control.Concurrent import Control.Exception @@ -142,8 +142,8 @@ data State = { sGen :: StdGen , sOffset :: Int , sMode :: Mode - , sHistory :: [RTree ()] - , sFuture :: [RTree ()] + , sHistory :: [R2Tree ()] + , sFuture :: [R2Tree ()] , sVao :: GLuint , sVbo :: GLuint } @@ -398,7 +398,7 @@ mbr (R.UnsafeMBR xmin ymin xmax ymax) rgb = , Point xmin_ ymin_ rgb ] -visualize :: Mode -> RTree a -> [Point] +visualize :: Mode -> R2Tree a -> [Point] visualize mode = visual 0 where wash i diff --git a/visualizer/r-tree-visualizer.cabal b/visualizer/r-tree-visualizer.cabal index ab0df8c..76dcd35 100644 --- a/visualizer/r-tree-visualizer.cabal +++ b/visualizer/r-tree-visualizer.cabal @@ -20,7 +20,7 @@ executable visualize build-depends: base >= 4.12 && < 5 , bytestring , colour - , data-r-tree + , r-tree , GLFW-b , gl , random From 9fd33de7794d7afd45b00540e3559d36fae8bcf7 Mon Sep 17 00:00:00 2001 From: BurningWitness Date: Tue, 3 Sep 2024 15:11:35 +0300 Subject: [PATCH 02/11] Updating README and resetting the CHANGELOG --- CHANGELOG.md | 4 +++ README.md | 15 ++++++-- changelog.md | 70 ------------------------------------ r-tree.cabal | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 73 deletions(-) create mode 100644 CHANGELOG.md delete mode 100644 changelog.md create mode 100644 r-tree.cabal diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8f100e3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +## 1.0.0.0 -- September 2024 + +- Initial rewrite. +- Library renamed from `data-r-tree`. diff --git a/README.md b/README.md index 8463c54..639da7d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,14 @@ -data-r-tree +r-tree [![Hackage](http://img.shields.io/hackage/v/r-tree.svg)](https://hackage.haskell.org/package/r-tree) ---- +A Haskell library for [R-](https://en.wikipedia.org/wiki/R-tree) and [R\*-trees](https://en.wikipedia.org/wiki/R\*-tree). -R/R\*-trees, currently only two-dimensional `Float` and `Double` varieties. +Featuring: + +- `Data.R2Tree.\*`: spine-strict two-dimensional R-tree. + + `Double`-based implementation is considered the default one; + a `Float`-based variant is provided for cases where reduced precision is preferred, + for example rendering. + +Three-dimensional R-trees are not currently available, +but should not trivial to add if needed. diff --git a/changelog.md b/changelog.md deleted file mode 100644 index e3d966b..0000000 --- a/changelog.md +++ /dev/null @@ -1,70 +0,0 @@ -## 1.2.0 - -Proper rewrite of the library. -Additions are not listed, only the most important changes are. - -* Cabal file changes: - - - Bumped lower boundary of `base` to `4.12`; - - - No longer depends on `binary`; - -* `MBB`: - - - Now called `MBR`; - - - No longer has `Binary`, `Ord` and `Generic` instances; - - - All relevant functions have been moved to `.Unsafe` modules; - -* `RTree`: - - - `Data.RTree` is now called `Data.RTree.D2.Double`; - - - Internals are now exposed in `Data.RTree.D2.Double.Unsafe`; - - - `Binary`, `Generic`, `Monoid` and `Semigroup` instances were removed; - - - `insertWith`, `union`, `unionWith` and `mapMaybe`, - `fromList`, `toList`, `keys` and `values` were removed; - - - `length` is now named `size`; - - - Conversions between lookup functions: - - - `lookup` is `\ba -> foldrRangeWithKey (equals ba) (\_ x _ -> Just x) Nothing`; - - - `intersect` is `\ba -> foldrRangeWithKey (intersects ba) (\_ -> (:)) []`; - - - `intersectWithKey` is - `\ba -> foldrRangeWithKey (intersects ba) (\bx x -> (:) (bx, x)) []`; - - - `lookupRange` is `\ba -> foldrRangeWithKey (containedBy ba) (\_ -> (:)) []`; - - - `lookupRangeWithKey` is - `\ba -> foldrRangeWithKey (containedBy ba) (\bx x -> (:) (bx, x)) []`; - - - `lookupContainsRange` is `\ba -> foldrRangeWithKey (contains ba) (\_ -> (:)) []`; - - - `lookupContainsRangeWithKey` is - `\ba -> foldrRangeWithKey (contains ba) (\bx x -> (:) (bx, x)) []`; - -## 0.6.0 - -* Add `lookupContainsRange` and `lookupContainsRangeWithKey`. -* Add `intersectWithKey` and `intersect`. -* Now supports GHC 8.4, 8.5 and 8.6. -* Removed `test-strict` flag. -* Minimal Bounding Box is now also an instance of `Ord` - -## 0.0.5.0 - -* changed the Functor instance of Data.RTree.Strict to be strict - -* Data.RTree.Strict.RTree is now a newtype of Data.RTree.RTree - -## 0.0.4.0 - -* Added Data.RTree.Strict - -* Added Data.Binary interface for GHC 7.6 diff --git a/r-tree.cabal b/r-tree.cabal new file mode 100644 index 0000000..878a514 --- /dev/null +++ b/r-tree.cabal @@ -0,0 +1,100 @@ +cabal-version: 2.2 + +name: r-tree +version: 1.0.0.0 +synopsis: R-trees. +description: R/R*-trees. + + See the + for a brief overview of the data structures included in this package. + +license: MIT +license-file: LICENSE +author: Sebastian Wagner, Birte Wagner, Oleksii Divak +maintainer: Oleksii Divak +copyright: Sebastian Wagner, Birte Wagner, Oleksii Divak +category: Data Structures +build-type: Simple + +extra-doc-files: CHANGELOG.md + README.md + +bug-reports: https://github.com/sebastian-philipp/r-tree/issues +homepage: https://github.com/sebastian-philipp/r-tree + +source-repository head + type: git + location: https://github.com/sebastian-philipp/r-tree.git + + + +library + build-depends: base >= 4.12 && < 5 + , deepseq >= 1.4.3 && < 1.6 + + hs-source-dirs: src + + exposed-modules: Data.R2Tree.Double + Data.R2Tree.Double.Debug + Data.R2Tree.Double.Unsafe + Data.R2Tree.Float + Data.R2Tree.Float.Debug + Data.R2Tree.Float.Unsafe + + other-modules: Data.R2Tree.Double.Internal + Data.R2Tree.Float.Internal + + ghc-options: -Wall + + default-language: Haskell2010 + +benchmark time + build-depends: base + , r-tree + , deepseq + , tasty-bench >= 0.3 && < 0.5 + , random >= 1.2 && < 1.3 + + type: exitcode-stdio-1.0 + + main-is: Main.hs + + ghc-options: -Wall + + hs-source-dirs: benchmark/time + + default-language: Haskell2010 + +benchmark space + build-depends: base + , r-tree + , random + , weigh >= 0.0.16 && < 0.1 + + type: exitcode-stdio-1.0 + + main-is: Main.hs + + ghc-options: -Wall + + hs-source-dirs: benchmark/space + + default-language: Haskell2010 + +test-suite properties + build-depends: base + , r-tree + , deepseq + , hspec >= 2 && < 2.12 + , random + + type: exitcode-stdio-1.0 + + main-is: Main.hs + + ghc-options: -Wall + + hs-source-dirs: no + , test/properties + + default-language: Haskell2010 From 9b106de76d5f75ee9ca24b533b2bf161896c09b3 Mon Sep 17 00:00:00 2001 From: BurningWitness Date: Tue, 3 Sep 2024 15:13:00 +0300 Subject: [PATCH 03/11] Fixing README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 639da7d..54dabdd 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -r-tree [![Hackage](http://img.shields.io/hackage/v/r-tree.svg)](https://hackage.haskell.org/package/r-tree) +# r-tree [![Hackage](http://img.shields.io/hackage/v/r-tree.svg)](https://hackage.haskell.org/package/r-tree) A Haskell library for [R-](https://en.wikipedia.org/wiki/R-tree) and [R\*-trees](https://en.wikipedia.org/wiki/R\*-tree). Featuring: -- `Data.R2Tree.\*`: spine-strict two-dimensional R-tree. +- `Data.R2Tree.*`: spine-strict two-dimensional R-tree. `Double`-based implementation is considered the default one; a `Float`-based variant is provided for cases where reduced precision is preferred, for example rendering. Three-dimensional R-trees are not currently available, -but should not trivial to add if needed. +but should be trivial to add if needed. From bf6119b4d63aa1302d3f003589ec01b1c1f18449 Mon Sep 17 00:00:00 2001 From: BurningWitness Date: Tue, 3 Sep 2024 15:17:41 +0300 Subject: [PATCH 04/11] Noting spine-strictness in the README --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 54dabdd..72916e4 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,13 @@ A Haskell library for [R-](https://en.wikipedia.org/wiki/R-tree) and [R\*-trees](https://en.wikipedia.org/wiki/R\*-tree). +> [!NOTE] +> +> R-trees are self-valancing and as such can only be spine-strict. + Featuring: -- `Data.R2Tree.*`: spine-strict two-dimensional R-tree. +- `Data.R2Tree.*`: two-dimensional R-tree. `Double`-based implementation is considered the default one; a `Float`-based variant is provided for cases where reduced precision is preferred, From 2f9f3a1ef1fc85ac77c2306d9827e10ddea62324 Mon Sep 17 00:00:00 2001 From: BurningWitness Date: Tue, 3 Sep 2024 15:18:15 +0300 Subject: [PATCH 05/11] Fixing README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 72916e4..af697c3 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A Haskell library for [R-](https://en.wikipedia.org/wiki/R-tree) and [R\*-trees] > [!NOTE] > -> R-trees are self-valancing and as such can only be spine-strict. +> R-trees are self-balancing and as such can only be spine-strict. Featuring: From 1c125a7fa5997ca56cd3ac577b2ceb8ef6b2786d Mon Sep 17 00:00:00 2001 From: BurningWitness Date: Wed, 4 Sep 2024 15:06:41 +0300 Subject: [PATCH 06/11] Unboxing most tuples --- src/Data/R2Tree/Double/Internal.hs | 306 ++++++++++++++--------------- src/Data/R2Tree/Float/Internal.hs | 306 ++++++++++++++--------------- 2 files changed, 294 insertions(+), 318 deletions(-) diff --git a/src/Data/R2Tree/Double/Internal.hs b/src/Data/R2Tree/Double/Internal.hs index 108765a..f7d98f1 100644 --- a/src/Data/R2Tree/Double/Internal.hs +++ b/src/Data/R2Tree/Double/Internal.hs @@ -69,7 +69,6 @@ module Data.R2Tree.Double.Internal import Control.Applicative import Control.DeepSeq -import Control.Exception (assert) import Data.Bits import Data.Foldable import Data.Functor.Classes @@ -1200,7 +1199,7 @@ insertGutRoot :: MBR -> a -> R2Tree a -> Gut a insertGutRoot bx x n = case n of Node2 ba a bb b -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case insertGut_ bx x be e of GutOne bo o -> GutOne (unionMBR bo bz) (Node2 bo o bz z) @@ -1209,7 +1208,7 @@ insertGutRoot bx x n = GutOne (union3MBR bl br bz) (Node3 bl l br r bz z) Node3 ba a bb b bc c -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case insertGut_ bx x be e of GutOne bo o -> GutOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1218,7 +1217,7 @@ insertGutRoot bx x n = GutOne (union4MBR bl br by bz) (Node4 bl l br r by y bz z) Node4 ba a bb b bc c bd d -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case insertGut_ bx x be e of GutOne bo o -> GutOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1258,7 +1257,7 @@ insertGut_ bx x = go go bn n = case n of Node2 ba a bb b -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case go be e of GutOne bo o -> GutOne (unionMBR bo bz) (Node2 bo o bz z) @@ -1267,7 +1266,7 @@ insertGut_ bx x = go GutOne (union3MBR bl br bz) (Node3 bl l br r bz z) Node3 ba a bb b bc c -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case go be e of GutOne bo o -> GutOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1276,7 +1275,7 @@ insertGut_ bx x = go GutOne (union4MBR bl br by bz) (Node4 bl l br r by y bz z) Node4 ba a bb b bc c bd d -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case go be e of GutOne bo o -> GutOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1319,7 +1318,7 @@ insertGutRootNode bx x depth n = GutOne (union3MBR ba bb bx) (Node3 ba a bb b bx x) | otherwise -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case insertGutNode bx x (depth - 1) be e of GutOne bo o -> GutOne (unionMBR bo bz) (Node2 bo o bz z) @@ -1332,7 +1331,7 @@ insertGutRootNode bx x depth n = GutOne (union4MBR ba bb bc bx) (Node4 ba a bb b bc c bx x) | otherwise -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case insertGutNode bx x (depth - 1) be e of GutOne bo o -> GutOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1350,7 +1349,7 @@ insertGutRootNode bx x depth n = GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) | otherwise -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case insertGutNode bx x (depth - 1) be e of GutOne bo o -> GutOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1363,11 +1362,8 @@ insertGutRootNode bx x depth n = Q3R (L2 bl' bm m bo o) (L3 br' bp p bq q bs s) -> GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) - _ -> assert False - (errorWithoutStackTrace "Data.R2Tree.Double.Internal.insertGutRootNode: reached a leaf") - n + _ -> errorWithoutStackTrace "Data.R2Tree.Double.Internal.insertGutRootNode: reached a leaf" -{-# INLINE insertGutNode #-} insertGutNode :: MBR -> R2Tree a -> Int -> MBR -> R2Tree a -> Gut a insertGutNode bx x = go where @@ -1378,7 +1374,7 @@ insertGutNode bx x = go GutOne (unionMBR bn bx) (Node3 ba a bb b bx x) | otherwise -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case go (depth - 1) be e of GutOne bo o -> GutOne (unionMBR bo bz) (Node2 bo o bz z) @@ -1391,7 +1387,7 @@ insertGutNode bx x = go GutOne (unionMBR bn bx) (Node4 ba a bb b bc c bx x) | otherwise -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case go (depth - 1) be e of GutOne bo o -> GutOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1409,7 +1405,7 @@ insertGutNode bx x = go GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) | otherwise -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case go (depth - 1) be e of GutOne bo o -> GutOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1422,9 +1418,7 @@ insertGutNode bx x = go Q3R (L2 bl' bm m bo o) (L3 br' bp p bq q bs s) -> GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) - _ -> assert False - (errorWithoutStackTrace "Data.R2Tree.Double.Internal.insertGutNode: reached a leaf") - n + _ -> errorWithoutStackTrace "Data.R2Tree.Double.Internal.insertGutNode: reached a leaf" @@ -1433,11 +1427,10 @@ insertGutNode bx x = go enlargement :: MBR -> MBR -> Double enlargement bx ba = areaMBR (unionMBR ba bx) - areaMBR ba -{-# INLINE leastEnlargement2 #-} -leastEnlargement2 :: MBR -> MBR -> a -> MBR -> a -> (MBR, a, MBR, a) +leastEnlargement2 :: MBR -> MBR -> a -> MBR -> a -> (# MBR, a, MBR, a #) leastEnlargement2 bx ba a bb b = - let aw = (ba, a, bb, b) - bw = (bb, b, ba, a) + let aw = (# ba, a, bb, b #) + bw = (# bb, b, ba, a #) in case enlargement bx ba `compare` enlargement bx bb of GT -> bw @@ -1445,14 +1438,14 @@ leastEnlargement2 bx ba a bb b = EQ | areaMBR ba <= areaMBR bb -> aw | otherwise -> bw -{-# INLINE leastEnlargement3 #-} -leastEnlargement3 :: MBR -> MBR -> a -> MBR -> a -> MBR -> a -> (MBR, a, MBR, a, MBR, a) +leastEnlargement3 + :: MBR -> MBR -> a -> MBR -> a -> MBR -> a -> (# MBR, a, MBR, a, MBR, a #) leastEnlargement3 bx ba a bb b bc c = - let aw = let (be, e, by, y) = leastEnlargement2 bx ba a bc c - in (be, e, by, y, bb, b) + let aw = let !(# be, e, by, y #) = leastEnlargement2 bx ba a bc c + in (# be, e, by, y, bb, b #) - bw = let (be, e, by, y) = leastEnlargement2 bx bb b bc c - in (be, e, by, y, ba, a) + bw = let !(# be, e, by, y #) = leastEnlargement2 bx bb b bc c + in (# be, e, by, y, ba, a #) in case enlargement bx ba `compare` enlargement bx bb of GT -> bw @@ -1460,144 +1453,133 @@ leastEnlargement3 bx ba a bb b bc c = EQ | areaMBR ba <= areaMBR bb -> aw | otherwise -> bw -{-# INLINE leastEnlargement4 #-} leastEnlargement4 :: MBR -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a - -> (MBR, a, MBR, a, MBR, a, MBR, a) + -> (# MBR, a, MBR, a, MBR, a, MBR, a #) leastEnlargement4 bx ba a bb b bc c bd d = - let (be, e, bn, n) = leastEnlargement2 bx ba a bb b - (bf, f, bo, o) = leastEnlargement2 bx bc c bd d - (bg, g, bp, p) = leastEnlargement2 bx be e bf f + let !(# be, e, bn, n #) = leastEnlargement2 bx ba a bb b + !(# bf, f, bo, o #) = leastEnlargement2 bx bc c bd d + !(# bg, g, bp, p #) = leastEnlargement2 bx be e bf f - in (bg, g, bn, n, bo, o, bp, p) + in (# bg, g, bn, n, bo, o, bp, p #) -data L2 a = L2 MBR MBR a MBR a +data L2 a = L2 !MBR !MBR a !MBR a -data L3 a = L3 MBR MBR a MBR a MBR a +data L3 a = L3 !MBR !MBR a !MBR a !MBR a -data Q1 a = Q1L (L2 a) MBR a - | Q1R MBR a (L2 a) +data Q1 a = Q1L !(L2 a) !MBR a + | Q1R !MBR a !(L2 a) -data Q2 a = Q2L (L3 a) MBR a - | Q2M (L2 a) (L2 a) - | Q2R MBR a (L3 a) +data Q2 a = Q2L !(L3 a) !MBR a + | Q2M !(L2 a) !(L2 a) + | Q2R !MBR a !(L3 a) -data Q3 a = Q3L (L3 a) (L2 a) - | Q3R (L2 a) (L3 a) +data Q3 a = Q3L !(L3 a) !(L2 a) + | Q3R !(L2 a) !(L3 a) -{-# NOINLINE quadSplit #-} quadSplit :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> Q3 a quadSplit ba a bb b bc c bd d be e = - let (bl, l, br, r, bx, x, by, y, bz, z) = pickSeeds ba a bb b bc c bd d be e - (q1, bv, v, bw, w) = distribute3 bl l br r bx x by y bz z - (q2, bu, u) = distribute2 q1 bv v bw w + let !(# bl, l, br, r, bx, x, by, y, bz, z #) = pickSeeds ba a bb b bc c bd d be e + !(# q1, bv, v, bw, w #) = distribute3 bl l br r bx x by y bz z + !(# q2, bu, u #) = distribute2 q1 bv v bw w in distribute1 q2 bu u -{-# INLINE pickSeeds #-} pickSeeds :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a - -> (MBR, a, MBR, a, MBR, a, MBR, a, MBR, a) + -> (# MBR, a, MBR, a, MBR, a, MBR, a, MBR, a #) pickSeeds ba a bb b bc c bd d be e = let waste bx by = areaMBR (unionMBR bx by) - areaMBR bx - areaMBR by - align x@( bw, _, bx, _, _, _, _, _, _, _ ) - y@( by, _, bz, _, _, _, _, _, _, _ ) + align x@(# bw, _, bx, _, _, _, _, _, _, _ #) + y@(# by, _, bz, _, _, _, _, _, _, _ #) | waste bw bx > waste by bz = x | otherwise = y - in align ( ba, a, bb, b, bc, c, bd, d, be, e ) - . align ( ba, a, bc, c, bb, b, bd, d, be, e ) - . align ( ba, a, bd, d, bb, b, bc, c, be, e ) - . align ( ba, a, be, e, bb, b, bc, c, bd, d ) - . align ( bb, b, bc, c, ba, a, bd, d, be, e ) - . align ( bb, b, bd, d, ba, a, bc, c, be, e ) - . align ( bb, b, be, e, ba, a, bc, c, bd, d ) - . align ( bc, c, bd, d, ba, a, bb, b, be, e ) - $ align ( bc, c, be, e, ba, a, bb, b, bd, d ) - ( bd, d, be, e, ba, a, bb, b, bc, c ) + in align (# ba, a, bb, b, bc, c, bd, d, be, e #) + ( align (# ba, a, bc, c, bb, b, bd, d, be, e #) + ( align (# ba, a, bd, d, bb, b, bc, c, be, e #) + ( align (# ba, a, be, e, bb, b, bc, c, bd, d #) + ( align (# bb, b, bc, c, ba, a, bd, d, be, e #) + ( align (# bb, b, bd, d, ba, a, bc, c, be, e #) + ( align (# bb, b, be, e, ba, a, bc, c, bd, d #) + ( align (# bc, c, bd, d, ba, a, bb, b, be, e #) + ( align (# bc, c, be, e, ba, a, bb, b, bd, d #) + (# bd, d, be, e, ba, a, bb, b, bc, c #) )))))))) -{-# INLINE distribute3 #-} distribute3 - :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> (Q1 a, MBR, a, MBR, a) + :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> (# Q1 a, MBR, a, MBR, a #) distribute3 bl l br r bx x by y bz z = let delta ba = abs (enlargement ba bl - enlargement ba br) - (be, !e, !bu, !u, !bv, !v) = if delta bx >= delta by - then if delta bx >= delta bz - then (bx, x, by, y, bz, z) - else (bz, z, bx, x, by, y) + !(# be, !e, !bu, !u, !bv, !v #) = if delta bx >= delta by + then if delta bx >= delta bz + then (# bx, x, by, y, bz, z #) + else (# bz, z, bx, x, by, y #) - else if delta by >= delta bz - then (by, y, bx, x, bz, z) - else (bz, z, bx, x, by, y) + else if delta by >= delta bz + then (# by, y, bx, x, bz, z #) + else (# bz, z, bx, x, by, y #) lw = Q1L (L2 (unionMBR bl be) bl l be e) br r rw = Q1R bl l (L2 (unionMBR br be) br r be e) - in ( case enlargement be bl `compare` enlargement be br of - GT -> rw - LT -> lw - EQ | areaMBR bl < areaMBR br -> lw - | otherwise -> rw - , bu - , u - , bv - , v - ) + !q1 = case enlargement be bl `compare` enlargement be br of + GT -> rw + LT -> lw + EQ | areaMBR bl < areaMBR br -> lw + | otherwise -> rw + in (# q1, bu, u, bv, v #) -{-# INLINE distribute2 #-} -distribute2 :: Q1 a -> MBR -> a -> MBR -> a -> (Q2 a, MBR, a) + +distribute2 :: Q1 a -> MBR -> a -> MBR -> a -> (# Q2 a, MBR, a #) distribute2 q bx x by y = let delta bl br bd = abs (enlargement bd bl - enlargement bd br) in case q of Q1L l@(L2 bl ba a bb b) br r -> - let (be, !e, !bz, !z) | delta bl br bx >= delta bl br by = (bx, x, by, y) - | otherwise = (by, y, bx, x) + let !(# be, !e, !bz, !z #) | delta bl br bx >= delta bl br by = (# bx, x, by, y #) + | otherwise = (# by, y, bx, x #) lw = Q2L (L3 (unionMBR bl be) ba a bb b be e) br r rw = Q2M l (L2 (unionMBR br be) br r be e) - in ( case enlargement be bl `compare` enlargement be br of - GT -> rw - LT -> lw - EQ | areaMBR bl <= areaMBR br -> lw - | otherwise -> rw - , bz - , z - ) + !q2 = case enlargement be bl `compare` enlargement be br of + GT -> rw + LT -> lw + EQ | areaMBR bl <= areaMBR br -> lw + | otherwise -> rw + + in (# q2, bz, z #) Q1R bl l r@(L2 br ba a bb b) -> - let (be, !e, !bz, !z) | delta bl br bx >= delta bl br by = (bx, x, by, y) - | otherwise = (by, y, bx, x) + let !(# be, !e, !bz, !z #) | delta bl br bx >= delta bl br by = (# bx, x, by, y #) + | otherwise = (# by, y, bx, x #) lw = Q2M (L2 (unionMBR bl be) bl l be e) r rw = Q2R bl l (L3 (unionMBR br be) ba a bb b be e) - in ( case enlargement be bl `compare` enlargement be br of - GT -> rw - LT -> lw - EQ | areaMBR bl <= areaMBR br -> lw - | otherwise -> rw - , bz - , z - ) + !q2 = case enlargement be bl `compare` enlargement be br of + GT -> rw + LT -> lw + EQ | areaMBR bl <= areaMBR br -> lw + | otherwise -> rw + + in (# q2, bz, z #) -{-# INLINE distribute1 #-} distribute1 :: Q2 a -> MBR -> a -> Q3 a distribute1 q bx x = case q of @@ -1633,7 +1615,7 @@ insert bx x n = case n of Node2 ba a bb b -> let add f bg g bh h = - let (be, e, !bz, !z) = leastEnlargement2 bx bg g bh h + let !(# be, e, !bz, !z #) = leastEnlargement2 bx bg g bh h in case f be e of InsOne bo o -> Node2 bo o bz z InsCarry mask carry bo o -> @@ -1650,7 +1632,7 @@ insert bx x n = Node3 ba a bb b bc c -> let add f bg g bh h bi i = - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx bg g bh h bi i + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx bg g bh h bi i in case f be e of InsOne bo o -> Node3 bo o by y bz z InsCarry mask carry bo o -> @@ -1667,7 +1649,7 @@ insert bx x n = Node4 ba a bb b bc c bd d -> let add f bg g bh h bi i bj j = - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx bg g bh h bi i bj j + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx bg g bh h bi i bj j in case f be e of InsOne bo o -> Node4 bo o bw w by y bz z InsCarry mask carry bo o -> @@ -1709,7 +1691,7 @@ insert_ mask bx x = go go height bn n = case n of Node2 ba a bb b -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case go (height + 1) be e of InsOne bo o -> InsOne (unionMBR bo bz) (Node2 bo o bz z) InsCarry mask' carry bo o -> @@ -1719,7 +1701,7 @@ insert_ mask bx x = go InsOne (union3MBR bl br bz) (Node3 bl l br r bz z) Node3 ba a bb b bc c -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case go (height + 1) be e of InsOne bo o -> InsOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1731,7 +1713,7 @@ insert_ mask bx x = go InsOne (union4MBR bl br by bz) (Node4 bl l br r by y bz z) Node4 ba a bb b bc c bd d -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case go (height + 1) be e of InsOne bo o -> InsOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1751,8 +1733,8 @@ insert_ mask bx x = go InsTwo mask bl' (Node2 bm m bo o) br' (Node3 bp p bs s bt t) _ -> - let (bm, m, bo, o, bp, p, bs, s, bt, t ) = - sort5 (distance (unionMBR bn bx)) bl l br r bw w by y bz z + let !(# bm, m, bo, o, bp, p, bs, s, bt, t #) = + sort5Distance (unionMBR bn bx) bl l br r bw w by y bz z in InsCarry (mask .|. bit_) (CarryNode height bt t) (union4MBR bm bo bp bs) (Node4 bm m bo o bp p bs s) @@ -1775,8 +1757,8 @@ insert_ mask bx x = go InsTwo mask bl (Leaf2 bu u bv v) br (Leaf3 bw w by y bz z) _ -> - let (bu, u, bv, v, bw, w, by, y, bz, z) = - sort5 (distance (unionMBR bn bx)) ba a bb b bc c bd d bx x + let !(# bu, u, bv, v, bw, w, by, y, bz, z #) = + sort5Distance (unionMBR bn bx) ba a bb b bc c bd d bx x in InsCarry (mask .|. bit_) (CarryLeaf bz z) (union4MBR bu bv bw by) (Leaf4 bu u bv v bw w by y) @@ -1795,7 +1777,7 @@ insertNode mask depth bx x = go case n of Node2 ba a bb b | height >= depth -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case go (height + 1) be e of InsOne bo o -> InsOne (unionMBR bo bz) (Node2 bo o bz z) InsCarry mask' carry bo o -> @@ -1809,7 +1791,7 @@ insertNode mask depth bx x = go Node3 ba a bb b bc c | height >= depth -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case go (height + 1) be e of InsOne bo o -> InsOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1825,7 +1807,7 @@ insertNode mask depth bx x = go Node4 ba a bb b bc c bd d | height >= depth -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case go (height + 1) be e of InsOne bo o -> InsOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1845,8 +1827,8 @@ insertNode mask depth bx x = go InsTwo mask bl' (Node2 bm m bo o) br' (Node3 bp p bs s bt t) _ -> - let (bm, m, bo, o, bp, p, bs, s, bt, t) = - sort5 (distance (unionMBR bn bx)) bl l br r bw w by y bz z + let !(# bm, m, bo, o, bp, p, bs, s, bt, t #) = + sort5Distance (unionMBR bn bx) bl l br r bw w by y bz z in InsCarry (mask .|. bit_) (CarryNode height bt t) (union4MBR bm bo bp bs) (Node4 bm m bo o bp p bs s) @@ -1863,31 +1845,28 @@ insertNode mask depth bx x = go InsTwo mask bl' (Node2 bm m bo o) br' (Node3 bp p bs s bt t) _ -> - let (bm, m, bo, o, bp, p, bs, s, bt, t) = - sort5 (distance (unionMBR bn bx)) ba a bb b bc c bd d bx x + let !(# bm, m, bo, o, bp, p, bs, s, bt, t #) = + sort5Distance (unionMBR bn bx) ba a bb b bc c bd d bx x in InsCarry (mask .|. bit_) (CarryNode height bt t) (union4MBR bm bo bp bs) (Node4 bm m bo o bp p bs s) - _ -> assert False - (errorWithoutStackTrace "Data.R2Tree.Double.Internal.insertNode: reached a leaf") - n + _ -> errorWithoutStackTrace "Data.R2Tree.Double.Internal.insertNode: reached a leaf" -{-# NOINLINE sortSplit #-} sortSplit :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> Q3 a sortSplit ba a bb b bc c bd d be e = - let v = sort5 vertical ba a bb b bc c bd d be e - h = sort5 horizontal ba a bb b bc c bd d be e + let v = sort5_ vertical ba a bb b bc c bd d be e + h = sort5_ horizontal ba a bb b bc c bd d be e vg = group v hg = group h - ( al@(L3 bu _ _ _ _ _ _), ar@(L2 bv _ _ _ _) - , bl@(L2 bx _ _ _ _), br@(L3 by _ _ _ _ _ _) ) + !(# al@(L3 bu _ _ _ _ _ _), ar@(L2 bv _ _ _ _) + , bl@(L2 bx _ _ _ _), br@(L3 by _ _ _ _ _ _) #) | margins vg <= margins hg = vg | otherwise = hg @@ -1902,6 +1881,16 @@ sortSplit ba a bb b bc c bd d be e = +sort5Distance + :: MBR + -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a + -> (# MBR, a, MBR, a, MBR, a, MBR, a, MBR, a #) +sort5Distance bx ka a kb b kc c kd d ke e = + sort5_ (distance bx) ka a kb b kc c kd d ke e + + + + {-# INLINE horizontal #-} horizontal :: MBR -> MBR -> Bool horizontal (UnsafeMBR xmin _ xmax _) (UnsafeMBR xmin' _ xmax' _) = @@ -1922,48 +1911,49 @@ vertical (UnsafeMBR _ ymin _ ymax) (UnsafeMBR _ ymin' _ ymax') = distance :: MBR -> MBR -> MBR -> Bool distance bx ba bb = distanceMBR bx ba <= distanceMBR bx bb -{-# INLINE sort5 #-} -sort5 +{-# INLINE sort5_ #-} +sort5_ :: (k -> k -> Bool) -- as in (A is smaller than B) -> k -> a -> k -> a -> k -> a -> k -> a -> k -> a - -> (k, a, k, a, k, a, k, a, k, a) -sort5 f ka a kb b kc c kd d ke e = + -> (# k, a, k, a, k, a, k, a, k, a #) +sort5_ f ka a kb b kc c kd d ke e = let swap kx x ky y - | f kx ky = (kx, x, ky, y) - | otherwise = (ky, y, kx, x) + | f kx ky = (# kx, x, ky, y #) + | otherwise = (# ky, y, kx, x #) sort3 kw w kx x ky y kz z | f kw ky = if f kw kx - then (kw, w, kx, x, ky, y, kz, z) - else (kx, x, kw, w, ky, y, kz, z) + then (# kw, w, kx, x, ky, y, kz, z #) + else (# kx, x, kw, w, ky, y, kz, z #) | otherwise = if f kw kz - then (kx, x, ky, y, kw, w, kz, z) - else (kx, x, ky, y, kz, z, kw, w) + then (# kx, x, ky, y, kw, w, kz, z #) + else (# kx, x, ky, y, kz, z, kw, w #) - (ka1, a1, kb1, b1) = swap ka a kb b - (kc1, c1, kd1, d1) = swap kc c kd d + (# ka1, a1, kb1, b1 #) = swap ka a kb b + (# kc1, c1, kd1, d1 #) = swap kc c kd d - (ka2, (a2, kb2, b2), kc2, (c2, kd2, d2)) = swap ka1 (a1, kb1, b1) kc1 (c1, kd1, d1) + (# ka2, (a2, kb2, b2), kc2, (c2, kd2, d2) #) = + swap ka1 (a1, kb1, b1) kc1 (c1, kd1, d1) - (ka3, a3, kc3, c3, kd3, d3, ke3, e3) = sort3 ke e ka2 a2 kc2 c2 kd2 d2 + (# ka3, a3, kc3, c3, kd3, d3, ke3, e3 #) = sort3 ke e ka2 a2 kc2 c2 kd2 d2 - (kb4, b4, kc4, c4, kd4, d4, ke4, e4) = sort3 kb2 b2 kc3 c3 kd3 d3 ke3 e3 + (# kb4, b4, kc4, c4, kd4, d4, ke4, e4 #) = sort3 kb2 b2 kc3 c3 kd3 d3 ke3 e3 - in (ka3, a3, kb4, b4, kc4, c4, kd4, d4, ke4, e4) + in (# ka3, a3, kb4, b4, kc4, c4, kd4, d4, ke4, e4 #) {-# INLINE group #-} group - :: (MBR, a, MBR, a, MBR, a, MBR, a, MBR, a) -> (L3 a, L2 a, L2 a, L3 a) -group (ba, a, bb, b, bc, c, bd, d, be, e) = - ( L3 (union3MBR ba bb bc) ba a bb b bc c, L2 (unionMBR bd be) bd d be e - , L2 (unionMBR ba bb) ba a bb b, L3 (union3MBR bd be bc) bd d be e bc c ) + :: (# MBR, a, MBR, a, MBR, a, MBR, a, MBR, a #) -> (# L3 a, L2 a, L2 a, L3 a #) +group (# ba, a, bb, b, bc, c, bd, d, be, e #) = + (# L3 (union3MBR ba bb bc) ba a bb b bc c, L2 (unionMBR bd be) bd d be e + , L2 (unionMBR ba bb) ba a bb b, L3 (union3MBR bd be bc) bd d be e bc c #) {-# INLINE margins #-} -margins :: (L3 a, L2 a, L2 a, L3 a) -> Double -margins (L3 bw _ _ _ _ _ _, L2 bx _ _ _ _, L2 by _ _ _ _, L3 bz _ _ _ _ _ _) = +margins :: (# L3 a, L2 a, L2 a, L3 a #) -> Double +margins (# L3 bw _ _ _ _ _ _, L2 bx _ _ _ _, L2 by _ _ _ _, L3 bz _ _ _ _ _ _ #) = marginMBR bw + marginMBR bx + marginMBR by + marginMBR bz @@ -1979,7 +1969,10 @@ delete bx s = DelOne _ o -> o DelNone -> s DelSome re _ o -> reintegrate 0 o re - DelRe re -> reconstruct re + DelRe re -> + case re of + ReCons _ _ n re' -> reintegrate (-1) n re' + ReLeaf ba a -> Leaf1 ba a where reintegrate height n re = case re of @@ -1993,11 +1986,7 @@ delete bx s = GutOne _ o -> o GutTwo bl l br r -> Node2 bl l br r - {-# INLINE reconstruct #-} - reconstruct re = - case re of - ReCons _ _ n re' -> reintegrate (-1) n re' - ReLeaf ba a -> Leaf1 ba a + data Re a = ReCons Int MBR (R2Tree a) (Re a) | ReLeaf MBR a @@ -2007,7 +1996,6 @@ data Del a = DelNone | DelSome (Re a) MBR (R2Tree a) | DelRe (Re a) -{-# INLINE delete_ #-} delete_ :: MBR -> Int -> R2Tree a -> Del a delete_ bx = go where diff --git a/src/Data/R2Tree/Float/Internal.hs b/src/Data/R2Tree/Float/Internal.hs index 74c63a0..0e0e7bd 100644 --- a/src/Data/R2Tree/Float/Internal.hs +++ b/src/Data/R2Tree/Float/Internal.hs @@ -69,7 +69,6 @@ module Data.R2Tree.Float.Internal import Control.Applicative import Control.DeepSeq -import Control.Exception (assert) import Data.Bits import Data.Foldable import Data.Functor.Classes @@ -1200,7 +1199,7 @@ insertGutRoot :: MBR -> a -> R2Tree a -> Gut a insertGutRoot bx x n = case n of Node2 ba a bb b -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case insertGut_ bx x be e of GutOne bo o -> GutOne (unionMBR bo bz) (Node2 bo o bz z) @@ -1209,7 +1208,7 @@ insertGutRoot bx x n = GutOne (union3MBR bl br bz) (Node3 bl l br r bz z) Node3 ba a bb b bc c -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case insertGut_ bx x be e of GutOne bo o -> GutOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1218,7 +1217,7 @@ insertGutRoot bx x n = GutOne (union4MBR bl br by bz) (Node4 bl l br r by y bz z) Node4 ba a bb b bc c bd d -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case insertGut_ bx x be e of GutOne bo o -> GutOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1258,7 +1257,7 @@ insertGut_ bx x = go go bn n = case n of Node2 ba a bb b -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case go be e of GutOne bo o -> GutOne (unionMBR bo bz) (Node2 bo o bz z) @@ -1267,7 +1266,7 @@ insertGut_ bx x = go GutOne (union3MBR bl br bz) (Node3 bl l br r bz z) Node3 ba a bb b bc c -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case go be e of GutOne bo o -> GutOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1276,7 +1275,7 @@ insertGut_ bx x = go GutOne (union4MBR bl br by bz) (Node4 bl l br r by y bz z) Node4 ba a bb b bc c bd d -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case go be e of GutOne bo o -> GutOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1319,7 +1318,7 @@ insertGutRootNode bx x depth n = GutOne (union3MBR ba bb bx) (Node3 ba a bb b bx x) | otherwise -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case insertGutNode bx x (depth - 1) be e of GutOne bo o -> GutOne (unionMBR bo bz) (Node2 bo o bz z) @@ -1332,7 +1331,7 @@ insertGutRootNode bx x depth n = GutOne (union4MBR ba bb bc bx) (Node4 ba a bb b bc c bx x) | otherwise -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case insertGutNode bx x (depth - 1) be e of GutOne bo o -> GutOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1350,7 +1349,7 @@ insertGutRootNode bx x depth n = GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) | otherwise -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case insertGutNode bx x (depth - 1) be e of GutOne bo o -> GutOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1363,11 +1362,8 @@ insertGutRootNode bx x depth n = Q3R (L2 bl' bm m bo o) (L3 br' bp p bq q bs s) -> GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) - _ -> assert False - (errorWithoutStackTrace "Data.R2Tree.Float.Internal.insertGutRootNode: reached a leaf") - n + _ -> errorWithoutStackTrace "Data.R2Tree.Float.Internal.insertGutRootNode: reached a leaf" -{-# INLINE insertGutNode #-} insertGutNode :: MBR -> R2Tree a -> Int -> MBR -> R2Tree a -> Gut a insertGutNode bx x = go where @@ -1378,7 +1374,7 @@ insertGutNode bx x = go GutOne (unionMBR bn bx) (Node3 ba a bb b bx x) | otherwise -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case go (depth - 1) be e of GutOne bo o -> GutOne (unionMBR bo bz) (Node2 bo o bz z) @@ -1391,7 +1387,7 @@ insertGutNode bx x = go GutOne (unionMBR bn bx) (Node4 ba a bb b bc c bx x) | otherwise -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case go (depth - 1) be e of GutOne bo o -> GutOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1409,7 +1405,7 @@ insertGutNode bx x = go GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) | otherwise -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case go (depth - 1) be e of GutOne bo o -> GutOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1422,9 +1418,7 @@ insertGutNode bx x = go Q3R (L2 bl' bm m bo o) (L3 br' bp p bq q bs s) -> GutTwo bl' (Node2 bm m bo o) br' (Node3 bp p bq q bs s) - _ -> assert False - (errorWithoutStackTrace "Data.R2Tree.Float.Internal.insertGutNode: reached a leaf") - n + _ -> errorWithoutStackTrace "Data.R2Tree.Float.Internal.insertGutNode: reached a leaf" @@ -1433,11 +1427,10 @@ insertGutNode bx x = go enlargement :: MBR -> MBR -> Float enlargement bx ba = areaMBR (unionMBR ba bx) - areaMBR ba -{-# INLINE leastEnlargement2 #-} -leastEnlargement2 :: MBR -> MBR -> a -> MBR -> a -> (MBR, a, MBR, a) +leastEnlargement2 :: MBR -> MBR -> a -> MBR -> a -> (# MBR, a, MBR, a #) leastEnlargement2 bx ba a bb b = - let aw = (ba, a, bb, b) - bw = (bb, b, ba, a) + let aw = (# ba, a, bb, b #) + bw = (# bb, b, ba, a #) in case enlargement bx ba `compare` enlargement bx bb of GT -> bw @@ -1445,14 +1438,14 @@ leastEnlargement2 bx ba a bb b = EQ | areaMBR ba <= areaMBR bb -> aw | otherwise -> bw -{-# INLINE leastEnlargement3 #-} -leastEnlargement3 :: MBR -> MBR -> a -> MBR -> a -> MBR -> a -> (MBR, a, MBR, a, MBR, a) +leastEnlargement3 + :: MBR -> MBR -> a -> MBR -> a -> MBR -> a -> (# MBR, a, MBR, a, MBR, a #) leastEnlargement3 bx ba a bb b bc c = - let aw = let (be, e, by, y) = leastEnlargement2 bx ba a bc c - in (be, e, by, y, bb, b) + let aw = let !(# be, e, by, y #) = leastEnlargement2 bx ba a bc c + in (# be, e, by, y, bb, b #) - bw = let (be, e, by, y) = leastEnlargement2 bx bb b bc c - in (be, e, by, y, ba, a) + bw = let !(# be, e, by, y #) = leastEnlargement2 bx bb b bc c + in (# be, e, by, y, ba, a #) in case enlargement bx ba `compare` enlargement bx bb of GT -> bw @@ -1460,144 +1453,133 @@ leastEnlargement3 bx ba a bb b bc c = EQ | areaMBR ba <= areaMBR bb -> aw | otherwise -> bw -{-# INLINE leastEnlargement4 #-} leastEnlargement4 :: MBR -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a - -> (MBR, a, MBR, a, MBR, a, MBR, a) + -> (# MBR, a, MBR, a, MBR, a, MBR, a #) leastEnlargement4 bx ba a bb b bc c bd d = - let (be, e, bn, n) = leastEnlargement2 bx ba a bb b - (bf, f, bo, o) = leastEnlargement2 bx bc c bd d - (bg, g, bp, p) = leastEnlargement2 bx be e bf f + let !(# be, e, bn, n #) = leastEnlargement2 bx ba a bb b + !(# bf, f, bo, o #) = leastEnlargement2 bx bc c bd d + !(# bg, g, bp, p #) = leastEnlargement2 bx be e bf f - in (bg, g, bn, n, bo, o, bp, p) + in (# bg, g, bn, n, bo, o, bp, p #) -data L2 a = L2 MBR MBR a MBR a +data L2 a = L2 !MBR !MBR a !MBR a -data L3 a = L3 MBR MBR a MBR a MBR a +data L3 a = L3 !MBR !MBR a !MBR a !MBR a -data Q1 a = Q1L (L2 a) MBR a - | Q1R MBR a (L2 a) +data Q1 a = Q1L !(L2 a) !MBR a + | Q1R !MBR a !(L2 a) -data Q2 a = Q2L (L3 a) MBR a - | Q2M (L2 a) (L2 a) - | Q2R MBR a (L3 a) +data Q2 a = Q2L !(L3 a) !MBR a + | Q2M !(L2 a) !(L2 a) + | Q2R !MBR a !(L3 a) -data Q3 a = Q3L (L3 a) (L2 a) - | Q3R (L2 a) (L3 a) +data Q3 a = Q3L !(L3 a) !(L2 a) + | Q3R !(L2 a) !(L3 a) -{-# NOINLINE quadSplit #-} quadSplit :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> Q3 a quadSplit ba a bb b bc c bd d be e = - let (bl, l, br, r, bx, x, by, y, bz, z) = pickSeeds ba a bb b bc c bd d be e - (q1, bv, v, bw, w) = distribute3 bl l br r bx x by y bz z - (q2, bu, u) = distribute2 q1 bv v bw w + let !(# bl, l, br, r, bx, x, by, y, bz, z #) = pickSeeds ba a bb b bc c bd d be e + !(# q1, bv, v, bw, w #) = distribute3 bl l br r bx x by y bz z + !(# q2, bu, u #) = distribute2 q1 bv v bw w in distribute1 q2 bu u -{-# INLINE pickSeeds #-} pickSeeds :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a - -> (MBR, a, MBR, a, MBR, a, MBR, a, MBR, a) + -> (# MBR, a, MBR, a, MBR, a, MBR, a, MBR, a #) pickSeeds ba a bb b bc c bd d be e = let waste bx by = areaMBR (unionMBR bx by) - areaMBR bx - areaMBR by - align x@( bw, _, bx, _, _, _, _, _, _, _ ) - y@( by, _, bz, _, _, _, _, _, _, _ ) + align x@(# bw, _, bx, _, _, _, _, _, _, _ #) + y@(# by, _, bz, _, _, _, _, _, _, _ #) | waste bw bx > waste by bz = x | otherwise = y - in align ( ba, a, bb, b, bc, c, bd, d, be, e ) - . align ( ba, a, bc, c, bb, b, bd, d, be, e ) - . align ( ba, a, bd, d, bb, b, bc, c, be, e ) - . align ( ba, a, be, e, bb, b, bc, c, bd, d ) - . align ( bb, b, bc, c, ba, a, bd, d, be, e ) - . align ( bb, b, bd, d, ba, a, bc, c, be, e ) - . align ( bb, b, be, e, ba, a, bc, c, bd, d ) - . align ( bc, c, bd, d, ba, a, bb, b, be, e ) - $ align ( bc, c, be, e, ba, a, bb, b, bd, d ) - ( bd, d, be, e, ba, a, bb, b, bc, c ) + in align (# ba, a, bb, b, bc, c, bd, d, be, e #) + ( align (# ba, a, bc, c, bb, b, bd, d, be, e #) + ( align (# ba, a, bd, d, bb, b, bc, c, be, e #) + ( align (# ba, a, be, e, bb, b, bc, c, bd, d #) + ( align (# bb, b, bc, c, ba, a, bd, d, be, e #) + ( align (# bb, b, bd, d, ba, a, bc, c, be, e #) + ( align (# bb, b, be, e, ba, a, bc, c, bd, d #) + ( align (# bc, c, bd, d, ba, a, bb, b, be, e #) + ( align (# bc, c, be, e, ba, a, bb, b, bd, d #) + (# bd, d, be, e, ba, a, bb, b, bc, c #) )))))))) -{-# INLINE distribute3 #-} distribute3 - :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> (Q1 a, MBR, a, MBR, a) + :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> (# Q1 a, MBR, a, MBR, a #) distribute3 bl l br r bx x by y bz z = let delta ba = abs (enlargement ba bl - enlargement ba br) - (be, !e, !bu, !u, !bv, !v) = if delta bx >= delta by - then if delta bx >= delta bz - then (bx, x, by, y, bz, z) - else (bz, z, bx, x, by, y) + !(# be, !e, !bu, !u, !bv, !v #) = if delta bx >= delta by + then if delta bx >= delta bz + then (# bx, x, by, y, bz, z #) + else (# bz, z, bx, x, by, y #) - else if delta by >= delta bz - then (by, y, bx, x, bz, z) - else (bz, z, bx, x, by, y) + else if delta by >= delta bz + then (# by, y, bx, x, bz, z #) + else (# bz, z, bx, x, by, y #) lw = Q1L (L2 (unionMBR bl be) bl l be e) br r rw = Q1R bl l (L2 (unionMBR br be) br r be e) - in ( case enlargement be bl `compare` enlargement be br of - GT -> rw - LT -> lw - EQ | areaMBR bl < areaMBR br -> lw - | otherwise -> rw - , bu - , u - , bv - , v - ) + !q1 = case enlargement be bl `compare` enlargement be br of + GT -> rw + LT -> lw + EQ | areaMBR bl < areaMBR br -> lw + | otherwise -> rw + in (# q1, bu, u, bv, v #) -{-# INLINE distribute2 #-} -distribute2 :: Q1 a -> MBR -> a -> MBR -> a -> (Q2 a, MBR, a) + +distribute2 :: Q1 a -> MBR -> a -> MBR -> a -> (# Q2 a, MBR, a #) distribute2 q bx x by y = let delta bl br bd = abs (enlargement bd bl - enlargement bd br) in case q of Q1L l@(L2 bl ba a bb b) br r -> - let (be, !e, !bz, !z) | delta bl br bx >= delta bl br by = (bx, x, by, y) - | otherwise = (by, y, bx, x) + let !(# be, !e, !bz, !z #) | delta bl br bx >= delta bl br by = (# bx, x, by, y #) + | otherwise = (# by, y, bx, x #) lw = Q2L (L3 (unionMBR bl be) ba a bb b be e) br r rw = Q2M l (L2 (unionMBR br be) br r be e) - in ( case enlargement be bl `compare` enlargement be br of - GT -> rw - LT -> lw - EQ | areaMBR bl <= areaMBR br -> lw - | otherwise -> rw - , bz - , z - ) + !q2 = case enlargement be bl `compare` enlargement be br of + GT -> rw + LT -> lw + EQ | areaMBR bl <= areaMBR br -> lw + | otherwise -> rw + + in (# q2, bz, z #) Q1R bl l r@(L2 br ba a bb b) -> - let (be, !e, !bz, !z) | delta bl br bx >= delta bl br by = (bx, x, by, y) - | otherwise = (by, y, bx, x) + let !(# be, !e, !bz, !z #) | delta bl br bx >= delta bl br by = (# bx, x, by, y #) + | otherwise = (# by, y, bx, x #) lw = Q2M (L2 (unionMBR bl be) bl l be e) r rw = Q2R bl l (L3 (unionMBR br be) ba a bb b be e) - in ( case enlargement be bl `compare` enlargement be br of - GT -> rw - LT -> lw - EQ | areaMBR bl <= areaMBR br -> lw - | otherwise -> rw - , bz - , z - ) + !q2 = case enlargement be bl `compare` enlargement be br of + GT -> rw + LT -> lw + EQ | areaMBR bl <= areaMBR br -> lw + | otherwise -> rw + + in (# q2, bz, z #) -{-# INLINE distribute1 #-} distribute1 :: Q2 a -> MBR -> a -> Q3 a distribute1 q bx x = case q of @@ -1633,7 +1615,7 @@ insert bx x n = case n of Node2 ba a bb b -> let add f bg g bh h = - let (be, e, !bz, !z) = leastEnlargement2 bx bg g bh h + let !(# be, e, !bz, !z #) = leastEnlargement2 bx bg g bh h in case f be e of InsOne bo o -> Node2 bo o bz z InsCarry mask carry bo o -> @@ -1650,7 +1632,7 @@ insert bx x n = Node3 ba a bb b bc c -> let add f bg g bh h bi i = - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx bg g bh h bi i + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx bg g bh h bi i in case f be e of InsOne bo o -> Node3 bo o by y bz z InsCarry mask carry bo o -> @@ -1667,7 +1649,7 @@ insert bx x n = Node4 ba a bb b bc c bd d -> let add f bg g bh h bi i bj j = - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx bg g bh h bi i bj j + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx bg g bh h bi i bj j in case f be e of InsOne bo o -> Node4 bo o bw w by y bz z InsCarry mask carry bo o -> @@ -1709,7 +1691,7 @@ insert_ mask bx x = go go height bn n = case n of Node2 ba a bb b -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case go (height + 1) be e of InsOne bo o -> InsOne (unionMBR bo bz) (Node2 bo o bz z) InsCarry mask' carry bo o -> @@ -1719,7 +1701,7 @@ insert_ mask bx x = go InsOne (union3MBR bl br bz) (Node3 bl l br r bz z) Node3 ba a bb b bc c -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case go (height + 1) be e of InsOne bo o -> InsOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1731,7 +1713,7 @@ insert_ mask bx x = go InsOne (union4MBR bl br by bz) (Node4 bl l br r by y bz z) Node4 ba a bb b bc c bd d -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case go (height + 1) be e of InsOne bo o -> InsOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1751,8 +1733,8 @@ insert_ mask bx x = go InsTwo mask bl' (Node2 bm m bo o) br' (Node3 bp p bs s bt t) _ -> - let (bm, m, bo, o, bp, p, bs, s, bt, t ) = - sort5 (distance (unionMBR bn bx)) bl l br r bw w by y bz z + let !(# bm, m, bo, o, bp, p, bs, s, bt, t #) = + sort5Distance (unionMBR bn bx) bl l br r bw w by y bz z in InsCarry (mask .|. bit_) (CarryNode height bt t) (union4MBR bm bo bp bs) (Node4 bm m bo o bp p bs s) @@ -1775,8 +1757,8 @@ insert_ mask bx x = go InsTwo mask bl (Leaf2 bu u bv v) br (Leaf3 bw w by y bz z) _ -> - let (bu, u, bv, v, bw, w, by, y, bz, z) = - sort5 (distance (unionMBR bn bx)) ba a bb b bc c bd d bx x + let !(# bu, u, bv, v, bw, w, by, y, bz, z #) = + sort5Distance (unionMBR bn bx) ba a bb b bc c bd d bx x in InsCarry (mask .|. bit_) (CarryLeaf bz z) (union4MBR bu bv bw by) (Leaf4 bu u bv v bw w by y) @@ -1795,7 +1777,7 @@ insertNode mask depth bx x = go case n of Node2 ba a bb b | height >= depth -> - let (be, e, !bz, !z) = leastEnlargement2 bx ba a bb b + let !(# be, e, !bz, !z #) = leastEnlargement2 bx ba a bb b in case go (height + 1) be e of InsOne bo o -> InsOne (unionMBR bo bz) (Node2 bo o bz z) InsCarry mask' carry bo o -> @@ -1809,7 +1791,7 @@ insertNode mask depth bx x = go Node3 ba a bb b bc c | height >= depth -> - let (be, e, !by, !y, !bz, !z) = leastEnlargement3 bx ba a bb b bc c + let !(# be, e, !by, !y, !bz, !z #) = leastEnlargement3 bx ba a bb b bc c in case go (height + 1) be e of InsOne bo o -> InsOne (union3MBR bo by bz) (Node3 bo o by y bz z) @@ -1825,7 +1807,7 @@ insertNode mask depth bx x = go Node4 ba a bb b bc c bd d | height >= depth -> - let (be, e, !bw, !w, !by, !y, !bz, !z) = leastEnlargement4 bx ba a bb b bc c bd d + let !(# be, e, !bw, !w, !by, !y, !bz, !z #) = leastEnlargement4 bx ba a bb b bc c bd d in case go (height + 1) be e of InsOne bo o -> InsOne (union4MBR bo bw by bz) (Node4 bo o bw w by y bz z) @@ -1845,8 +1827,8 @@ insertNode mask depth bx x = go InsTwo mask bl' (Node2 bm m bo o) br' (Node3 bp p bs s bt t) _ -> - let (bm, m, bo, o, bp, p, bs, s, bt, t) = - sort5 (distance (unionMBR bn bx)) bl l br r bw w by y bz z + let !(# bm, m, bo, o, bp, p, bs, s, bt, t #) = + sort5Distance (unionMBR bn bx) bl l br r bw w by y bz z in InsCarry (mask .|. bit_) (CarryNode height bt t) (union4MBR bm bo bp bs) (Node4 bm m bo o bp p bs s) @@ -1863,31 +1845,28 @@ insertNode mask depth bx x = go InsTwo mask bl' (Node2 bm m bo o) br' (Node3 bp p bs s bt t) _ -> - let (bm, m, bo, o, bp, p, bs, s, bt, t) = - sort5 (distance (unionMBR bn bx)) ba a bb b bc c bd d bx x + let !(# bm, m, bo, o, bp, p, bs, s, bt, t #) = + sort5Distance (unionMBR bn bx) ba a bb b bc c bd d bx x in InsCarry (mask .|. bit_) (CarryNode height bt t) (union4MBR bm bo bp bs) (Node4 bm m bo o bp p bs s) - _ -> assert False - (errorWithoutStackTrace "Data.R2Tree.Float.Internal.insertNode: reached a leaf") - n + _ -> errorWithoutStackTrace "Data.R2Tree.Float.Internal.insertNode: reached a leaf" -{-# NOINLINE sortSplit #-} sortSplit :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> Q3 a sortSplit ba a bb b bc c bd d be e = - let v = sort5 vertical ba a bb b bc c bd d be e - h = sort5 horizontal ba a bb b bc c bd d be e + let v = sort5_ vertical ba a bb b bc c bd d be e + h = sort5_ horizontal ba a bb b bc c bd d be e vg = group v hg = group h - ( al@(L3 bu _ _ _ _ _ _), ar@(L2 bv _ _ _ _) - , bl@(L2 bx _ _ _ _), br@(L3 by _ _ _ _ _ _) ) + !(# al@(L3 bu _ _ _ _ _ _), ar@(L2 bv _ _ _ _) + , bl@(L2 bx _ _ _ _), br@(L3 by _ _ _ _ _ _) #) | margins vg <= margins hg = vg | otherwise = hg @@ -1902,6 +1881,16 @@ sortSplit ba a bb b bc c bd d be e = +sort5Distance + :: MBR + -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a + -> (# MBR, a, MBR, a, MBR, a, MBR, a, MBR, a #) +sort5Distance bx ka a kb b kc c kd d ke e = + sort5_ (distance bx) ka a kb b kc c kd d ke e + + + + {-# INLINE horizontal #-} horizontal :: MBR -> MBR -> Bool horizontal (UnsafeMBR xmin _ xmax _) (UnsafeMBR xmin' _ xmax' _) = @@ -1922,48 +1911,49 @@ vertical (UnsafeMBR _ ymin _ ymax) (UnsafeMBR _ ymin' _ ymax') = distance :: MBR -> MBR -> MBR -> Bool distance bx ba bb = distanceMBR bx ba <= distanceMBR bx bb -{-# INLINE sort5 #-} -sort5 +{-# INLINE sort5_ #-} +sort5_ :: (k -> k -> Bool) -- as in (A is smaller than B) -> k -> a -> k -> a -> k -> a -> k -> a -> k -> a - -> (k, a, k, a, k, a, k, a, k, a) -sort5 f ka a kb b kc c kd d ke e = + -> (# k, a, k, a, k, a, k, a, k, a #) +sort5_ f ka a kb b kc c kd d ke e = let swap kx x ky y - | f kx ky = (kx, x, ky, y) - | otherwise = (ky, y, kx, x) + | f kx ky = (# kx, x, ky, y #) + | otherwise = (# ky, y, kx, x #) sort3 kw w kx x ky y kz z | f kw ky = if f kw kx - then (kw, w, kx, x, ky, y, kz, z) - else (kx, x, kw, w, ky, y, kz, z) + then (# kw, w, kx, x, ky, y, kz, z #) + else (# kx, x, kw, w, ky, y, kz, z #) | otherwise = if f kw kz - then (kx, x, ky, y, kw, w, kz, z) - else (kx, x, ky, y, kz, z, kw, w) + then (# kx, x, ky, y, kw, w, kz, z #) + else (# kx, x, ky, y, kz, z, kw, w #) - (ka1, a1, kb1, b1) = swap ka a kb b - (kc1, c1, kd1, d1) = swap kc c kd d + (# ka1, a1, kb1, b1 #) = swap ka a kb b + (# kc1, c1, kd1, d1 #) = swap kc c kd d - (ka2, (a2, kb2, b2), kc2, (c2, kd2, d2)) = swap ka1 (a1, kb1, b1) kc1 (c1, kd1, d1) + (# ka2, (a2, kb2, b2), kc2, (c2, kd2, d2) #) = + swap ka1 (a1, kb1, b1) kc1 (c1, kd1, d1) - (ka3, a3, kc3, c3, kd3, d3, ke3, e3) = sort3 ke e ka2 a2 kc2 c2 kd2 d2 + (# ka3, a3, kc3, c3, kd3, d3, ke3, e3 #) = sort3 ke e ka2 a2 kc2 c2 kd2 d2 - (kb4, b4, kc4, c4, kd4, d4, ke4, e4) = sort3 kb2 b2 kc3 c3 kd3 d3 ke3 e3 + (# kb4, b4, kc4, c4, kd4, d4, ke4, e4 #) = sort3 kb2 b2 kc3 c3 kd3 d3 ke3 e3 - in (ka3, a3, kb4, b4, kc4, c4, kd4, d4, ke4, e4) + in (# ka3, a3, kb4, b4, kc4, c4, kd4, d4, ke4, e4 #) {-# INLINE group #-} group - :: (MBR, a, MBR, a, MBR, a, MBR, a, MBR, a) -> (L3 a, L2 a, L2 a, L3 a) -group (ba, a, bb, b, bc, c, bd, d, be, e) = - ( L3 (union3MBR ba bb bc) ba a bb b bc c, L2 (unionMBR bd be) bd d be e - , L2 (unionMBR ba bb) ba a bb b, L3 (union3MBR bd be bc) bd d be e bc c ) + :: (# MBR, a, MBR, a, MBR, a, MBR, a, MBR, a #) -> (# L3 a, L2 a, L2 a, L3 a #) +group (# ba, a, bb, b, bc, c, bd, d, be, e #) = + (# L3 (union3MBR ba bb bc) ba a bb b bc c, L2 (unionMBR bd be) bd d be e + , L2 (unionMBR ba bb) ba a bb b, L3 (union3MBR bd be bc) bd d be e bc c #) {-# INLINE margins #-} -margins :: (L3 a, L2 a, L2 a, L3 a) -> Float -margins (L3 bw _ _ _ _ _ _, L2 bx _ _ _ _, L2 by _ _ _ _, L3 bz _ _ _ _ _ _) = +margins :: (# L3 a, L2 a, L2 a, L3 a #) -> Float +margins (# L3 bw _ _ _ _ _ _, L2 bx _ _ _ _, L2 by _ _ _ _, L3 bz _ _ _ _ _ _ #) = marginMBR bw + marginMBR bx + marginMBR by + marginMBR bz @@ -1979,7 +1969,10 @@ delete bx s = DelOne _ o -> o DelNone -> s DelSome re _ o -> reintegrate 0 o re - DelRe re -> reconstruct re + DelRe re -> + case re of + ReCons _ _ n re' -> reintegrate (-1) n re' + ReLeaf ba a -> Leaf1 ba a where reintegrate height n re = case re of @@ -1993,11 +1986,7 @@ delete bx s = GutOne _ o -> o GutTwo bl l br r -> Node2 bl l br r - {-# INLINE reconstruct #-} - reconstruct re = - case re of - ReCons _ _ n re' -> reintegrate (-1) n re' - ReLeaf ba a -> Leaf1 ba a + data Re a = ReCons Int MBR (R2Tree a) (Re a) | ReLeaf MBR a @@ -2007,7 +1996,6 @@ data Del a = DelNone | DelSome (Re a) MBR (R2Tree a) | DelRe (Re a) -{-# INLINE delete_ #-} delete_ :: MBR -> Int -> R2Tree a -> Del a delete_ bx = go where From f80d0f8dbc718a95ebd9e309198f283cbd3489ce Mon Sep 17 00:00:00 2001 From: BurningWitness Date: Wed, 4 Sep 2024 15:10:07 +0300 Subject: [PATCH 07/11] Checking to see if Github's CI works out of the box --- .circleci/config.yml | 55 --------------------------------------- .github/workflow/ci.yaml | 56 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 55 deletions(-) delete mode 100644 .circleci/config.yml create mode 100644 .github/workflow/ci.yaml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 6f7c690..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,55 +0,0 @@ -version: 2.1 - -jobs: - build: - machine: - image: ubuntu-2004:current - resource_class: medium - parameters: - version: - type: string - steps: - - checkout - - restore_cache: - name: Restore - key: linux-<< parameters.version >>-{{ checksum "r-tree.cabal" }} - - run: - name: Install GHC - command: | - sudo add-apt-repository ppa:hvr/ghc - sudo apt-get install ghc-<< parameters.version >> cabal-install-3.4 - echo 'export PATH=/opt/ghc/bin:$PATH' >> $BASH_ENV - - - run: - name: Update Dependencies - command: cabal new-update - - run: - name: Build - command: cabal new-build --enable-tests --enable-documentation - - save_cache: - name: Cache - key: linux-<< parameters.version >>-{{ checksum "r-tree.cabal" }} - paths: - - "/root/.cabal" - - "dist-newstyle" - - run: - name: Test - command: cabal new-test --enable-documentation --test-show-details=streaming - - - -workflows: - workflow: - jobs: - - build: - name: linux-8.6.5 - version: 8.6.5 - - build: - name: linux-8.8.4 - version: 8.8.4 - - build: - name: linux-8.10.4 - version: 8.10.4 - - build: - name: linux-9.0.1 - version: 9.0.1 diff --git a/.github/workflow/ci.yaml b/.github/workflow/ci.yaml new file mode 100644 index 0000000..707e691 --- /dev/null +++ b/.github/workflow/ci.yaml @@ -0,0 +1,56 @@ +name: CI +on: + - push + - pull_request + +defaults: + run: + shell: bash + +jobs: + main: + name: GHC ${{ matrix.ghc }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + + # https://github.com/orgs/community/discussions/57827 + if: github.event_name != 'pull_request' || + github.event.pull_request.head.repo.full_name != + github.event.pull_request.base.repo.full_name + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + ghc: + - "9.0" + - "9.2" + - "9.4" + - "9.6" + - "9.8" + - "9.10" + + steps: + + - uses: actions/checkout@v4 + + - uses: haskell-actions/setup@v2 + id: setup-haskell-cabal + with: + ghc-version: ${{ matrix.ghc }} + + - uses: actions/cache@v4 + name: Cache cabal stuff + with: + path: | + ${{ steps.setup-haskell-cabal.outputs.cabal-store }} + dist-newstyle + key: ${{ runner.os }}-${{ matrix.ghc }} + + - name: Cabal version + run: | + cabal --version + + - name: Build & Test + run: | + cabal build --enable-tests + cabal test --enable-tests --test-show-details=direct properties From d09fecfa582d365247bed2f742db4b7995803066 Mon Sep 17 00:00:00 2001 From: BurningWitness Date: Wed, 4 Sep 2024 15:13:15 +0300 Subject: [PATCH 08/11] Fixing CI directory naming --- .github/{workflow => workflows}/ci.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{workflow => workflows}/ci.yaml (100%) diff --git a/.github/workflow/ci.yaml b/.github/workflows/ci.yaml similarity index 100% rename from .github/workflow/ci.yaml rename to .github/workflows/ci.yaml From 61256da43f49f2e1afee77de78559fade7ae6e9e Mon Sep 17 00:00:00 2001 From: BurningWitness Date: Wed, 4 Sep 2024 16:21:27 +0300 Subject: [PATCH 09/11] Making insertion benchmarks more strict --- benchmark/time/Main.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark/time/Main.hs b/benchmark/time/Main.hs index c46aeb0..0f31035 100644 --- a/benchmark/time/Main.hs +++ b/benchmark/time/Main.hs @@ -97,10 +97,10 @@ traversal cat from name pre = fromList :: Foldable t => t (MBR, b) -> R2Tree b -fromList = foldr (uncurry R.insert) R.empty +fromList = foldl' (\z (a, b) -> R.insert a b z) R.empty fromListGut :: Foldable t => t (MBR, b) -> R2Tree b -fromListGut = foldr (uncurry R.insertGut) R.empty +fromListGut = foldl' (\z (a, b) -> R.insertGut a b z) R.empty main :: IO () From 0ef414785e7264f1929dd7c9bf8c63689256a83b Mon Sep 17 00:00:00 2001 From: BurningWitness Date: Wed, 4 Sep 2024 16:22:34 +0300 Subject: [PATCH 10/11] Rewording the README --- README.md | 6 +++--- r-tree.cabal | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index af697c3..910bcaf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # r-tree [![Hackage](http://img.shields.io/hackage/v/r-tree.svg)](https://hackage.haskell.org/package/r-tree) -A Haskell library for [R-](https://en.wikipedia.org/wiki/R-tree) and [R\*-trees](https://en.wikipedia.org/wiki/R\*-tree). +A Haskell library for [R-trees](https://en.wikipedia.org/wiki/R-tree) and [R\*-trees](https://en.wikipedia.org/wiki/R\*-tree). > [!NOTE] > @@ -8,11 +8,11 @@ A Haskell library for [R-](https://en.wikipedia.org/wiki/R-tree) and [R\*-trees] Featuring: -- `Data.R2Tree.*`: two-dimensional R-tree. +- `Data.R2Tree.*`: two-dimensional R-tree with the R\*-tree insertion algorithm. `Double`-based implementation is considered the default one; a `Float`-based variant is provided for cases where reduced precision is preferred, for example rendering. -Three-dimensional R-trees are not currently available, +Higher-dimensional R-trees are not currently provided, but should be trivial to add if needed. diff --git a/r-tree.cabal b/r-tree.cabal index 878a514..425ed9c 100644 --- a/r-tree.cabal +++ b/r-tree.cabal @@ -2,8 +2,8 @@ cabal-version: 2.2 name: r-tree version: 1.0.0.0 -synopsis: R-trees. -description: R/R*-trees. +synopsis: R-/R*-trees. +description: R-trees and R*-trees. See the for a brief overview of the data structures included in this package. From 2cc9554f4de05b179fc7a9aa8421559e1c01eaf0 Mon Sep 17 00:00:00 2001 From: BurningWitness Date: Wed, 4 Sep 2024 16:25:48 +0300 Subject: [PATCH 11/11] Adding extra construction functions --- src/Data/R2Tree/Double.hs | 18 ++++++++++++++++++ src/Data/R2Tree/Float.hs | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/Data/R2Tree/Double.hs b/src/Data/R2Tree/Double.hs index a04dff2..b2ebe5b 100644 --- a/src/Data/R2Tree/Double.hs +++ b/src/Data/R2Tree/Double.hs @@ -81,6 +81,9 @@ module Data.R2Tree.Double -- * Construct , empty , singleton + , doubleton + , tripleton + , quadrupleton -- ** Bulk-loading , bulkSTR @@ -163,3 +166,18 @@ empty = Empty -- Tree with a single entry. singleton :: MBR -> a -> R2Tree a singleton = Leaf1 + +-- | \(\mathcal{O}(1)\). +-- Tree with two entries. +doubleton :: MBR -> a -> MBR -> a -> R2Tree a +doubleton = Leaf2 + +-- | \(\mathcal{O}(1)\). +-- Tree with three entries. +tripleton :: MBR -> a -> MBR -> a -> MBR -> a -> R2Tree a +tripleton = Leaf3 + +-- | \(\mathcal{O}(1)\). +-- Tree with four entries. +quadrupleton :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> R2Tree a +quadrupleton = Leaf4 diff --git a/src/Data/R2Tree/Float.hs b/src/Data/R2Tree/Float.hs index 6953e8a..ba863c9 100644 --- a/src/Data/R2Tree/Float.hs +++ b/src/Data/R2Tree/Float.hs @@ -21,6 +21,9 @@ module Data.R2Tree.Float -- * Construct , empty , singleton + , doubleton + , tripleton + , quadrupleton -- ** Bulk-loading , bulkSTR @@ -103,3 +106,18 @@ empty = Empty -- Tree with a single entry. singleton :: MBR -> a -> R2Tree a singleton = Leaf1 + +-- | \(\mathcal{O}(1)\). +-- Tree with two entries. +doubleton :: MBR -> a -> MBR -> a -> R2Tree a +doubleton = Leaf2 + +-- | \(\mathcal{O}(1)\). +-- Tree with three entries. +tripleton :: MBR -> a -> MBR -> a -> MBR -> a -> R2Tree a +tripleton = Leaf3 + +-- | \(\mathcal{O}(1)\). +-- Tree with four entries. +quadrupleton :: MBR -> a -> MBR -> a -> MBR -> a -> MBR -> a -> R2Tree a +quadrupleton = Leaf4