packages feed

hgeometry-combinatorial 0.12.0.3 → 0.13

raw patch · 19 files changed

+525/−162 lines, 19 filesdep ~semigroupoidsPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: semigroupoids

API changes (from Hackage documentation)

- Data.Ext.Multi: class HasCore extras
- Data.Ext.Multi: class HasExtras extras extras'
- Data.Ext.Multi: core :: HasCore extras => Lens (core :+ extras) (core' :+ extras) core core'
- Data.Ext.Multi: data family core :+ (extras :: [*]) :: *
- Data.Ext.Multi: ext :: c -> c :+ '[]
- Data.Ext.Multi: extra :: HasExtras extras extras' => Lens (core :+ extras) (core :+ extras') (HList extras) (HList extras')
- Data.Ext.Multi: infixr 1 :+
- Data.Ext.Multi: instance Control.DeepSeq.NFData core => Control.DeepSeq.NFData (core Data.Ext.Multi.:+ '[])
- Data.Ext.Multi: instance Data.Ext.Multi.HasCore '[]
- Data.Ext.Multi: instance Data.Ext.Multi.HasCore (t : ts)
- Data.Ext.Multi: instance Data.Ext.Multi.HasExtras '[] '[]
- Data.Ext.Multi: instance Data.Ext.Multi.HasExtras '[] (t : ts)
- Data.Ext.Multi: instance Data.Ext.Multi.HasExtras (t : ts) '[]
- Data.Ext.Multi: instance Data.Ext.Multi.HasExtras (t : ts) (a : as)
- Data.Ext.Multi: instance GHC.Classes.Eq core => GHC.Classes.Eq (core Data.Ext.Multi.:+ '[])
- Data.Ext.Multi: instance GHC.Classes.Ord core => GHC.Classes.Ord (core Data.Ext.Multi.:+ '[])
- Data.Ext.Multi: instance GHC.Generics.Generic (core Data.Ext.Multi.:+ '[])
- Data.Ext.Multi: instance GHC.Show.Show core => GHC.Show.Show (core Data.Ext.Multi.:+ '[])
- Data.Ext.Multi: instance Test.QuickCheck.Arbitrary.Arbitrary core => Test.QuickCheck.Arbitrary.Arbitrary (core Data.Ext.Multi.:+ '[])
- Data.Ext.Multi: pattern (:+) :: c -> HList (e : extras) -> c :+ (e : extras)
- Data.Set.Util: test :: Maybe S
+ Algorithms.LogarithmicMethod: InsertionOnly :: [Maybe (static a)] -> InsertionOnly static a
+ Algorithms.LogarithmicMethod: build :: LogarithmicMethodDS static a => NonEmpty a -> static a
+ Algorithms.LogarithmicMethod: class LogarithmicMethodDS static a
+ Algorithms.LogarithmicMethod: empty :: InsertionOnly static a
+ Algorithms.LogarithmicMethod: insert :: LogarithmicMethodDS static a => a -> InsertionOnly static a -> InsertionOnly static a
+ Algorithms.LogarithmicMethod: instance Algorithms.LogarithmicMethod.LogarithmicMethodDS static a => GHC.Base.Monoid (Algorithms.LogarithmicMethod.InsertionOnly static a)
+ Algorithms.LogarithmicMethod: instance Algorithms.LogarithmicMethod.LogarithmicMethodDS static a => GHC.Base.Semigroup (Algorithms.LogarithmicMethod.InsertionOnly static a)
+ Algorithms.LogarithmicMethod: instance Data.Foldable.Foldable static => Data.Foldable.Foldable (Algorithms.LogarithmicMethod.InsertionOnly static)
+ Algorithms.LogarithmicMethod: instance Data.Traversable.Traversable static => Data.Traversable.Traversable (Algorithms.LogarithmicMethod.InsertionOnly static)
+ Algorithms.LogarithmicMethod: instance GHC.Base.Functor static => GHC.Base.Functor (Algorithms.LogarithmicMethod.InsertionOnly static)
+ Algorithms.LogarithmicMethod: instance forall k (static :: k -> *) (a :: k). GHC.Classes.Eq (static a) => GHC.Classes.Eq (Algorithms.LogarithmicMethod.InsertionOnly static a)
+ Algorithms.LogarithmicMethod: instance forall k (static :: k -> *) (a :: k). GHC.Classes.Ord (static a) => GHC.Classes.Ord (Algorithms.LogarithmicMethod.InsertionOnly static a)
+ Algorithms.LogarithmicMethod: instance forall k (static :: k -> *) (a :: k). GHC.Show.Show (static a) => GHC.Show.Show (Algorithms.LogarithmicMethod.InsertionOnly static a)
+ Algorithms.LogarithmicMethod: merge :: (LogarithmicMethodDS static a, Foldable1 static) => static a -> static a -> static a
+ Algorithms.LogarithmicMethod: newtype InsertionOnly static a
+ Algorithms.LogarithmicMethod: queryWith :: Monoid m => (static a -> m) -> InsertionOnly static a -> m
+ Algorithms.LogarithmicMethod: singleton :: LogarithmicMethodDS static a => a -> static a
+ Data.Intersection: class HasIntersectionWith g h
+ Data.LSeq: reverse :: LSeq n a -> LSeq n a
+ Data.PlanarGraph: nextIncidentEdgeFrom :: Dart s -> PlanarGraph s w v e f -> Dart s
+ Data.PlanarGraph: prevIncidentEdgeFrom :: Dart s -> PlanarGraph s w v e f -> Dart s
+ Data.PlanarGraph.AdjRep: instance (GHC.Classes.Eq e, GHC.Classes.Eq v) => GHC.Classes.Eq (Data.PlanarGraph.AdjRep.Vtx v e)
+ Data.PlanarGraph.AdjRep: instance (GHC.Classes.Eq v, GHC.Classes.Eq f) => GHC.Classes.Eq (Data.PlanarGraph.AdjRep.Gr v f)
+ Data.PlanarGraph.AdjRep: instance (GHC.Show.Show e, GHC.Show.Show v) => GHC.Show.Show (Data.PlanarGraph.AdjRep.Vtx v e)
+ Data.PlanarGraph.AdjRep: instance (GHC.Show.Show v, GHC.Show.Show f) => GHC.Show.Show (Data.PlanarGraph.AdjRep.Gr v f)
+ Data.PlanarGraph.AdjRep: instance GHC.Classes.Eq f => GHC.Classes.Eq (Data.PlanarGraph.AdjRep.Face f)
+ Data.PlanarGraph.AdjRep: instance GHC.Show.Show f => GHC.Show.Show (Data.PlanarGraph.AdjRep.Face f)
+ Data.PlanarGraph.Core: nextIncidentEdgeFrom :: Dart s -> PlanarGraph s w v e f -> Dart s
+ Data.PlanarGraph.Core: prevIncidentEdgeFrom :: Dart s -> PlanarGraph s w v e f -> Dart s
+ Data.Range: instance GHC.Classes.Ord a => Data.Intersection.HasIntersectionWith (Data.Range.Range a) (Data.Range.Range a)
- Data.Intersection: class IsIntersectableWith g h
+ Data.Intersection: class HasIntersectionWith g h => IsIntersectableWith g h
- Data.Intersection: intersects :: IsIntersectableWith g h => g -> h -> Bool
+ Data.Intersection: intersects :: (HasIntersectionWith g h, IsIntersectableWith g h) => g -> h -> Bool
- Data.Permutation: indexes :: forall a_aqQP. Lens' (Permutation a_aqQP) (Vector (Int, Int))
+ Data.Permutation: indexes :: forall a_arfH. Lens' (Permutation a_arfH) (Vector (Int, Int))
- Data.Permutation: orbits :: forall a_aqQP a_aqZ7. Lens (Permutation a_aqQP) (Permutation a_aqZ7) (Vector (Orbit a_aqQP)) (Vector (Orbit a_aqZ7))
+ Data.Permutation: orbits :: forall a_arfH a_arnZ. Lens (Permutation a_arfH) (Permutation a_arnZ) (Vector (Orbit a_arfH)) (Vector (Orbit a_arnZ))

Files

changelog view
@@ -2,6 +2,16 @@  * Changelog +** 0.13++- Moved 'intersects' from the HasIntersectionWith class into a new+  class IsIntersectableWith. This allows separate (weaker) constraints+  for checking *if* geometries intersect rather than computing exact+  intersections.+- Bug fixes in the orientations of boundaries in PlanarGraph.+- Implementation of Logaritmic Method, wich allows us to transform a+  static data structure into an insertion only data structure+ ** 0.12  - Add Data.Double.Approximate: Floating point numbers take take
changelog.org view
@@ -2,6 +2,16 @@  * Changelog +** 0.13++- Moved 'intersects' from the HasIntersectionWith class into a new+  class IsIntersectableWith. This allows separate (weaker) constraints+  for checking *if* geometries intersect rather than computing exact+  intersections.+- Bug fixes in the orientations of boundaries in PlanarGraph.+- Implementation of Logaritmic Method, wich allows us to transform a+  static data structure into an insertion only data structure+ ** 0.12  - Add Data.Double.Approximate: Floating point numbers take take
hgeometry-combinatorial.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                hgeometry-combinatorial-version:             0.12.0.3+version:             0.13 synopsis:            Data structures, and Data types. description:     The Non-geometric data types and algorithms used in HGeometry.@@ -46,6 +46,7 @@                     -- * Algorithmic Strategies                     Algorithms.DivideAndConquer                     Algorithms.BinarySearch+                    Algorithms.LogarithmicMethod                      -- * Graph Algorithms                     Algorithms.Graph.DFS@@ -56,6 +57,9 @@                      Algorithms.StringSearch.KMP +++                     -- * Numeric Data Types                     Data.RealNumber.Rational                     Data.Double.Approximate@@ -72,7 +76,7 @@                     Data.Range                      Data.Ext-                    Data.Ext.Multi+                    -- Data.Ext.Multi                      Data.LSeq                     Data.CircularSeq@@ -129,6 +133,7 @@               , bifunctors              >= 4.1               , bytestring              >= 0.10               , containers              >= 0.5.9+              -- , data-default               , dlist                   >= 0.7               , lens                    >= 4.18               , contravariant           >= 1.5@@ -223,6 +228,7 @@    other-modules: Algorithms.StringSearch.KMPSpec                  Algorithms.DivideAndConquerSpec+                 Algorithms.LogarithmicMethodSpec                  Algorithms.Graph.DFSSpec                  Algorithms.Graph.BFSSpec                  Data.RangeSpec@@ -254,6 +260,7 @@                       , directory                       , yaml                       , MonadRandom+                      , semigroupoids   -- -- Such a mess:   -- if impl(ghc == 9.*)   --   build-depends:      singletons              == 3.*
+ src/Algorithms/LogarithmicMethod.hs view
@@ -0,0 +1,151 @@+{-# LANGUAGE DefaultSignatures #-}+--------------------------------------------------------------------------------+-- |+-- Module      :  Algorithms.LogarithmicMethod+-- Copyright   :  (C) Frank Staals+-- License     :  see the LICENSE file+-- Maintainer  :  Frank Staals+--------------------------------------------------------------------------------+module Algorithms.LogarithmicMethod+  ( InsertionOnly(..)+  , empty+  , LogarithmicMethodDS(..)+  , insert+  , queryWith+  )+  where++import Data.List.NonEmpty (NonEmpty(..))+import Data.Maybe (mapMaybe)+import Data.Semigroup.Foldable++--------------------------------------------------------------------------------++-- | Represents an insertion-only data structure built from static+-- data structures.+--+-- In particular, we maintain \(O(\log n)\) static data structures of+-- sizes \(2^i\), for \(i \in [0..c\log n]\).+newtype InsertionOnly static a = InsertionOnly [Maybe (static a)]+  deriving (Show,Eq,Ord)++-- | Builds an empty structure+empty :: InsertionOnly static a+empty = InsertionOnly []++instance Functor static => Functor (InsertionOnly static) where+  fmap f (InsertionOnly dss) = InsertionOnly $ map (fmap (fmap f)) dss++instance Traversable static => Traversable (InsertionOnly static) where+  traverse f (InsertionOnly dss) = InsertionOnly <$> traverse (traverse (traverse f)) dss++instance Foldable static => Foldable (InsertionOnly static) where+  foldMap f = queryWith (foldMap f)+  length = sum . mapMaybe (uncurry (<$)) . withSizes++instance LogarithmicMethodDS static a => Semigroup (InsertionOnly static a) where+  (InsertionOnly ds1) <> (InsertionOnly ds2) = InsertionOnly $ runMergeWith Nothing ds1 0 ds2 0++instance LogarithmicMethodDS static a => Monoid (InsertionOnly static a) where+  mempty = empty+++class LogarithmicMethodDS static a where+  {-# MINIMAL build #-}+  -- | Create a new static data structure storing only one value.+  singleton :: a          -> static a+  singleton = build . (:| [])++  -- | Given a NonEmpty list of a's build a static a.+  build     :: NonEmpty a -> static a++  -- | Merges two structurs of the same size. Has a default+  -- implementation via build in case the static structure is Foldable1.+  merge     :: static a   -> static a -> static a+  default merge :: Foldable1 static => static a -> static a -> static a+  merge as bs = build $ toNonEmpty as <> toNonEmpty bs+++type Power = Word++-- | 2^h, for whatever value h.+pow2   :: Integral i => Power -> i+pow2 h = 2 ^ h++-- | Annotate the data structures with their sizes+withSizes                     :: Integral i => InsertionOnly static a -> [(i,Maybe (static a))]+withSizes (InsertionOnly dss) = zipWith (\i ds -> (pow2 i,ds))  [0..] dss++-- | Inserts an element into the data structure+--+-- running time: \(O(M(n)\log n / n)\), where \(M(n)\) is the time+-- required to merge two data structures of size \(n\).+insert                       :: LogarithmicMethodDS static a+                             => a -> InsertionOnly static a -> InsertionOnly static a+insert x (InsertionOnly dss) = InsertionOnly $ runMerge (singleton x) 0 0 dss++-- | Runs the merging procedure. If there are two data structures of+-- the same size they are merged.+runMerge         :: LogarithmicMethodDS static a+                 => static a -- ^ ds1+                 -> Power    -- ^ ds1 has size 2^i+                 -> Power    -- ^ the first entry in the next list corresponds to size 2^j+                 -> [Maybe (static a)] -> [Maybe (static a)]+runMerge ds1 i j = \case+  []                                -> [Just ds1]+  dss@(Nothing  : dss') | i == j    -> Just ds1 : dss' -- replace+                        | otherwise -> Just ds1 : dss  -- cons+  dss@(Just ds2 : dss') | i == j    -> Nothing : runMerge (ds1 `merge` ds2) (i+1) (j+1) dss'+                        | otherwise -> Just ds1 : dss -- cons -- I don't think insert can ever+                                                              -- trigger this scenario.++-- | merges two structures (potentially with a carry)+--+-- invariant: size carry == size ds1 <= size ds2+runMergeWith                ::  LogarithmicMethodDS static a+                            => Maybe (static a) -- ^ carry, if it exists+                            -> [Maybe (static a)] -> Power+                            -- ^ size of the first ds+                            -> [Maybe (static a)] -> Power+                            -- ^ size of the second ds+                            -> [Maybe (static a)]+runMergeWith mc ds1 i ds2 j = case (ds1,ds2) of+  ([],_)            -> case mc of+                         Nothing  -> ds2+                         Just c   -> runMerge c i j ds2+  (_,[])            -> case mc of+                         Nothing  -> ds1+                         Just c   -> runMerge c i i ds1+  (m1:ds1',m2:ds2') -> case (m1,m2) of+    (Nothing,Nothing) -> mc : runMergeWith Nothing ds1' (i+1) ds2' (j+1)+    (Nothing,Just d2) -> case mc of+         Nothing | i == j    -> m2 : runMergeWith Nothing ds1' (i+1) ds2' (j+1)+                 | otherwise -> m1 : runMergeWith Nothing ds1' (i+1) ds2 j+         Just c  | i == j    -> Nothing : runMergeWith (Just $ c `merge` d2) ds1' (i+1) ds2' (j+1)+                 | otherwise -> mc : runMergeWith Nothing ds1' (i+1) ds2 j+                   -- i < j, so invariant (i+1) <= j again holds holds++    (Just d1,Nothing) -> case mc of+                           Nothing -> m1 : runMergeWith Nothing ds1' (i+1) ds2' (j+1)+                           Just c  -> Nothing : runMergeWith (Just $ c `merge` d1) ds1' (i+1) ds2' (j+1)++    (Just d1,Just d2) -> case mc of+         Nothing | i == j    -> Nothing : runMergeWith (Just $ d1 `merge` d2) ds1' (i+1) ds2' (j+1)+                 | otherwise -> m1      : runMergeWith Nothing ds1' (i+1) ds2 j++         Just c  | i == j    -> mc : runMergeWith (Just $ d1 `merge` d2) ds1' (i+1) ds2' (j+1)+                 | otherwise -> Nothing : runMergeWith (Just $ c `merge` d1) ds1' (i+1) ds2 j+                       -- i < j, so invariant holds++-- | Given a decomposable query algorithm for the static structure,+-- lift it to a query algorithm on the insertion only structure.+--+-- pre: (As indicated by the Monoid constraint), the query answer+-- should be decomposable. I.e. we should be able to anser the query+-- on a set \(A \cup B\) by answering the query on \(A\) and \(B\)+-- separately, and combining their results.+--+-- running time: \(O(Q(n)\log n)\), where \(Q(n)\) is the query time+-- on the static structure.+queryWith                           :: Monoid m => (static a -> m) -> InsertionOnly static a -> m+queryWith query (InsertionOnly dss) = foldMap (foldMap query) dss
src/Data/Ext.hs view
@@ -21,6 +21,7 @@ import Data.Bifoldable import Data.Bifunctor.Apply import Data.Bitraversable+-- import Data.Default import Data.Functor.Apply (liftF2) import Data.Semigroup.Bifoldable import Data.Semigroup.Bitraversable@@ -73,6 +74,9 @@  instance (Arbitrary c, Arbitrary e) => Arbitrary (c :+ e) where   arbitrary = (:+) <$> arbitrary <*> arbitrary++-- instance (Default a, Default b) => Default (a :+ b) where+--   def = def :+ def  -- | Access the core of an extended value. _core :: (core :+ extra) -> core
− src/Data/Ext/Multi.hs
@@ -1,62 +0,0 @@------------------------------------------------------------------------------------ |--- Module      :  Data.Ext--- Copyright   :  (C) Frank Staals--- License     :  see the LICENSE file--- Maintainer  :  Frank Staals------ A pair-like data type to represent a 'core' type that has extra information--- as well.-------------------------------------------------------------------------------------module Data.Ext.Multi where--import Control.DeepSeq-import Control.Lens-import Data.Coerce-import Data.Vinyl-import GHC.Generics (Generic)-import Test.QuickCheck------------------------------------------------------------------------------------data family core :+ (extras :: [*]) :: *--newtype instance core :+ '[]    = Only core deriving (Eq,Ord,NFData,Arbitrary,Generic,Show)-data    instance core :+ (t:ts) = WithExtra !core (HList (t:ts))---infixr 1 :+--pattern (:+)   :: c -> HList (e:extras) -> c :+ (e:extras)-pattern c :+ r = WithExtra c r-{-# COMPLETE (:+) #-}--ext :: c -> c :+ '[]-ext = Only------------------------------------------------------------------------------------class HasCore extras where-  core :: Lens (core :+ extras) (core' :+ extras) core core'--instance HasCore '[] where-  core = lens coerce (const coerce)-instance HasCore (t:ts) where-  core = lens (\(c :+ _) -> c) (\(_ :+ r) c -> c :+ r)------------------------------------------------------------------------------------class HasExtras extras extras' where-  extra :: Lens (core :+ extras) (core :+ extras') (HList extras) (HList extras')--instance HasExtras '[] '[] where-  extra = lens (const RNil) const-instance HasExtras '[] (t:ts) where-  extra = lens (const RNil) (\(Only c) r -> c :+ r)-instance HasExtras (t:ts) '[] where-  extra = lens (\(_ :+ r) -> r) (\(c :+ _) _ -> Only c)-instance HasExtras (t:ts) (a:as) where-  extra = lens (\(_ :+ r) -> r) (\(c :+ _) r' -> c :+ r')----------------------------------------------------------------------------------
src/Data/Intersection.hs view
@@ -35,17 +35,19 @@ coRec :: (a ∈ as) => a -> CoRec Identity as coRec = CoRec . Identity --- | Class relationship between intersectable geometric objects.-class IsIntersectableWith g h where-  intersect :: g -> h -> Intersection g h-+class HasIntersectionWith g h where   -- | g `intersects` h  <=> The intersection of g and h is non-empty.   --   -- The default implementation computes the intersection of g and h,   -- and uses nonEmptyIntersection to determine if the intersection is   -- non-empty.   intersects :: g -> h -> Bool+  default intersects :: IsIntersectableWith g h => g -> h -> Bool   g `intersects` h = nonEmptyIntersection (Identity g) (Identity h) $ g `intersect` h++-- | Class relationship between intersectable geometric objects.+class HasIntersectionWith g h => IsIntersectableWith g h where+  intersect :: g -> h -> Intersection g h    -- | Helper to implement `intersects`.   nonEmptyIntersection :: proxy g -> proxy h -> Intersection g h -> Bool
src/Data/LSeq.hs view
@@ -29,6 +29,7 @@                 , unstableSort, unstableSortBy                 , head, tail, last, init                 , append+                , reverse                  , ViewL(..)                 , viewl@@ -57,7 +58,7 @@ import qualified Data.Traversable as Tr import           GHC.Generics (Generic) import           GHC.TypeLits-import           Prelude hiding (drop,take,head,last,tail,init,zipWith)+import           Prelude hiding (drop,take,head,last,tail,init,zipWith,reverse) import           Test.QuickCheck (Arbitrary(..),vector)  --------------------------------------------------------------------------------@@ -229,6 +230,11 @@  wrapUnsafe :: (S.Seq a -> S.Seq b) -> LSeq n a -> LSeq m b wrapUnsafe f = LSeq . f . toSeq++-- | Reverses the sequence.+reverse :: LSeq n a -> LSeq n a+reverse = wrapUnsafe S.reverse+  -------------------------------------------------------------------------------- 
src/Data/PlanarGraph.hs view
@@ -45,6 +45,7 @@                        , tailOf, headOf, endPoints                        , incidentEdges, incomingEdges, outgoingEdges, neighboursOf                        , nextIncidentEdge, prevIncidentEdge+                       , nextIncidentEdgeFrom, prevIncidentEdgeFrom                         -- * Associated Data @@ -69,10 +70,12 @@  -------------------------------------------------------------------------------- -- $setup+-- >>> import qualified Data.Vector as V+-- >>> import Control.Lens -- >>> :{ -- let dart i s = Dart (Arc i) (read s) --     (aA:aB:aC:aD:aE:aG:_) = take 6 [Arc 0..]---     myGraph :: PlanarGraph () Primal () String ()+--     myGraph :: PlanarGraph () Primal String String String --     myGraph = planarGraph [ [ (Dart aA Negative, "a-") --                             , (Dart aC Positive, "c+") --                             , (Dart aB Positive, "b+")@@ -89,7 +92,10 @@ --                             ] --                           , [ (Dart aG Negative, "g-") --                             ]---                           ]+--                           ] & vertexData .~ V.fromList ["u","v","w","x"]+--                             & faceData   .~ V.fromList ["f_3", "f_infty","f_1","f_2"]+--     showWithData     :: HasDataOf s i => s -> i -> (i, DataOf s i)+--     showWithData g i = (i, g^.dataOf i) -- :} -- --@@ -97,8 +103,6 @@ -- arrows are just to indicate what the Positive direction of the darts is. -- -- ![myGraph](docs/Data/PlanarGraph/testG.png)--   --------------------------------------------------------------------------------
src/Data/PlanarGraph/AdjRep.hs view
@@ -21,7 +21,7 @@ -- | Data type representing the graph in its JSON/Yaml format data Gr v f = Gr { adjacencies :: [v]                  , faces       :: [f]-                 } deriving (Generic)+                 } deriving (Generic, Show, Eq)  instance Bifunctor Gr where   bimap f g (Gr vs fs) = Gr (map f vs) (map g fs)@@ -44,7 +44,7 @@                                         -- vertices. This is not (yet)                                         -- enforced by the data type.                    , vData :: v-                   } deriving (Generic)+                   } deriving (Generic, Show, Eq)  instance Bifunctor Vtx where   bimap f g (Vtx i as x) = Vtx i (map (second g) as) (f x)@@ -59,7 +59,7 @@ data Face f = Face { incidentEdge :: (Int,Int) -- ^ an edge (u,v) s.t. the face                                                -- is right from (u,v)                    , fData        :: f-                   } deriving (Generic,Functor)+                   } deriving (Generic,Functor, Show, Eq)  instance ToJSON f   => ToJSON   (Face f) where   toEncoding = genericToEncoding defaultOptions
src/Data/PlanarGraph/Core.hs view
@@ -24,6 +24,7 @@ import           GHC.Generics               (Generic) import           Unsafe.Coerce              (unsafeCoerce) + --------------------------------------------------------------------------------  --------------------------------------------------------------------------------@@ -31,7 +32,7 @@ -- >>> :{ -- let dart i s = Dart (Arc i) (read s) --     (aA:aB:aC:aD:aE:aG:_) = take 6 [Arc 0..]---     myGraph :: PlanarGraph () Primal () String ()+--     myGraph :: PlanarGraph () Primal String String String --     myGraph = planarGraph [ [ (Dart aA Negative, "a-") --                             , (Dart aC Positive, "c+") --                             , (Dart aB Positive, "b+")@@ -48,7 +49,10 @@ --                             ] --                           , [ (Dart aG Negative, "g-") --                             ]---                           ]+--                           ] & vertexData .~ V.fromList ["u","v","w","x"]+--                             & faceData   .~ V.fromList ["f_3", "f_infty","f_1","f_2"]+--     showWithData     :: HasDataOf s i => s -> i -> (i, DataOf s i)+--     showWithData g i = (i, g^.dataOf i) -- :} -- --@@ -185,6 +189,9 @@                  (V.Vector (Dart s, e)) (V.Vector (Dart s, e')) edgeData = dartData +++ -- | Helper function to update the data in a planar graph. Takes care to update -- both the data in the original graph as well as in the dual. updateData :: forall s w v e f v' e' f'@@ -226,12 +233,12 @@ -- | Traverse the vertices -- -- >>> (^.vertexData) <$> traverseVertices (\i x -> Just (i,x)) myGraph--- Just [(VertexId 0,()),(VertexId 1,()),(VertexId 2,()),(VertexId 3,())]+-- Just [(VertexId 0,"u"),(VertexId 1,"v"),(VertexId 2,"w"),(VertexId 3,"x")] -- >>> traverseVertices (\i x -> print (i,x)) myGraph >> pure ()--- (VertexId 0,())--- (VertexId 1,())--- (VertexId 2,())--- (VertexId 3,())+-- (VertexId 0,"u")+-- (VertexId 1,"v")+-- (VertexId 2,"w")+-- (VertexId 3,"x") traverseVertices   :: Applicative m                    => (VertexId s w -> v -> m v')                    -> PlanarGraph s w v e f@@ -262,10 +269,10 @@ -- | Traverses the faces -- -- >>> traverseFaces (\i x -> print (i,x)) myGraph >> pure ()--- (FaceId 0,())--- (FaceId 1,())--- (FaceId 2,())--- (FaceId 3,())+-- (FaceId 0,"f_3")+-- (FaceId 1,"f_infty")+-- (FaceId 2,"f_1")+-- (FaceId 3,"f_2") traverseFaces   :: Applicative m                 => (FaceId s w -> f -> m f')                 -> PlanarGraph s w v e f@@ -408,36 +415,59 @@  -- | The tail of a dart, i.e. the vertex this dart is leaving from --+-- >>> showWithData myGraph $ tailOf (Dart (Arc 3) Positive) myGraph+-- (VertexId 2,"w")+-- -- running time: \(O(1)\) tailOf     :: Dart s -> PlanarGraph s w v e f -> VertexId s w tailOf d g = VertexId . fst $ lookupIdx (g^.embedding) d  -- | The vertex this dart is heading in to --+-- showWithData myGraph $ headOf (Dart (Arc 3) Positive) myGraph+-- (VertexId 1,"v")+-- -- running time: \(O(1)\) headOf   :: Dart s -> PlanarGraph s w v e f -> VertexId s w headOf d = tailOf (twin d)  -- | endPoints d g = (tailOf d g, headOf d g) --+-- >>> endPoints (Dart (Arc 3) Positive) myGraph+-- (VertexId 2,VertexId 1)+-- -- running time: \(O(1)\) endPoints :: Dart s -> PlanarGraph s w v e f -> (VertexId s w, VertexId s w) endPoints d g = (tailOf d g, headOf d g) - -- | All edges incident to vertex v, in counterclockwise order around v. -----+-- >>> incidentEdges (VertexId 1) myGraph+-- [Dart (Arc 4) -1,Dart (Arc 1) -1,Dart (Arc 3) -1,Dart (Arc 5) +1]+-- >>> mapM_ (print . showWithData myGraph) $ incidentEdges (VertexId 1) myGraph+-- (Dart (Arc 4) -1,"e-")+-- (Dart (Arc 1) -1,"b-")+-- (Dart (Arc 3) -1,"d-")+-- (Dart (Arc 5) +1,"g+")+-- >>> mapM_ (print . showWithData myGraph) $ incidentEdges (VertexId 3) myGraph+-- (Dart (Arc 5) -1,"g-") -- -- running time: \(O(k)\), where \(k\) is the output size incidentEdges                :: VertexId s w -> PlanarGraph s w v e f                              -> V.Vector (Dart s) incidentEdges (VertexId v) g = g^?!embedding.orbits.ix v-  -- TODO: The Delaunay triang. stuff seems to produce these in clockwise order instead  -- | All edges incident to vertex v in incoming direction -- (i.e. pointing into v) in counterclockwise order around v. --+-- >>> incomingEdges (VertexId 1) myGraph+-- [Dart (Arc 4) +1,Dart (Arc 1) +1,Dart (Arc 3) +1,Dart (Arc 5) -1]+-- >>> mapM_ (print . showWithData myGraph) $ incomingEdges (VertexId 1) myGraph+-- (Dart (Arc 4) +1,"e+")+-- (Dart (Arc 1) +1,"b+")+-- (Dart (Arc 3) +1,"d+")+-- (Dart (Arc 5) -1,"g-")+-- -- running time: \(O(k)\), where \(k) is the total number of incident edges of v incomingEdges     :: VertexId s w -> PlanarGraph s w v e f -> V.Vector (Dart s) incomingEdges v g = orient <$> incidentEdges v g@@ -457,30 +487,79 @@ -- | Gets the neighbours of a particular vertex, in counterclockwise order -- around the vertex. --+-- >>> mapM_ (print . showWithData myGraph) $ neighboursOf (VertexId 1) myGraph -- around v+-- (VertexId 2,"w")+-- (VertexId 0,"u")+-- (VertexId 2,"w")+-- (VertexId 3,"x")+-- >>> mapM_ (print . showWithData myGraph) $ neighboursOf (VertexId 3) myGraph -- around x+-- (VertexId 1,"v")+-- -- running time: \(O(k)\), where \(k\) is the output size neighboursOf     :: VertexId s w -> PlanarGraph s w v e f -> V.Vector (VertexId s w) neighboursOf v g = flip tailOf g <$> incomingEdges v g  -- | Given a dart d that points into some vertex v, report the next dart in the--- cyclic order around v.+-- cyclic (counterclockwise) order around v. --+-- >>> nextIncidentEdge (dart 3 "+1") myGraph+-- Dart (Arc 5) +1+-- >>> showWithData myGraph $ nextIncidentEdge (dart 3 "+1") myGraph+-- (Dart (Arc 5) +1,"g+")+-- >>> showWithData myGraph $ nextIncidentEdge (dart 1 "+1") myGraph+-- (Dart (Arc 3) -1,"d-")+-- -- running time: \(O(1)\)-nextIncidentEdge     :: Dart s -> PlanarGraph s w v e f -> Dart s-nextIncidentEdge d g = let perm  = g^.embedding-                           (i,j) = lookupIdx perm d-                       in next (perm^?!orbits.ix i) j+nextIncidentEdge   :: Dart s -> PlanarGraph s w v e f -> Dart s+nextIncidentEdge d = nextIncidentEdgeFrom (twin d) +-- | Given a dart d that points into some vertex v, report the previous dart in the+-- cyclic (counterclockwise) order around v.+--+-- >>> prevIncidentEdge (dart 3 "+1") myGraph+-- Dart (Arc 1) -1+-- >>> showWithData myGraph $ prevIncidentEdge (dart 3 "+1") myGraph+-- (Dart (Arc 1) -1,"b-")+--+-- running time: \(O(1)\)+prevIncidentEdge   :: Dart s -> PlanarGraph s w v e f -> Dart s+prevIncidentEdge d = prevIncidentEdgeFrom (twin d) --- | Given a dart d that points into some vertex v, report the next dart in the--- cyclic order around v.++-- | Given a dart d that points away from some vertex v, report the+-- next dart in the cyclic (counterclockwise) order around v. --+-- >>> nextIncidentEdgeFrom (Dart (Arc 3) Positive) myGraph+-- Dart (Arc 2) -1+-- >>> showWithData myGraph $ nextIncidentEdgeFrom (Dart (Arc 3) Positive) myGraph+-- (Dart (Arc 2) -1,"c-")+-- >>> showWithData myGraph $ nextIncidentEdgeFrom (dart 1 "+1") myGraph+-- (Dart (Arc 0) +1,"a+")+-- -- running time: \(O(1)\)-prevIncidentEdge     :: Dart s -> PlanarGraph s w v e f -> Dart s-prevIncidentEdge d g = let perm  = g^.embedding-                           (i,j) = lookupIdx perm d-                       in previous (perm^?!orbits.ix i) j+nextIncidentEdgeFrom     :: Dart s -> PlanarGraph s w v e f -> Dart s+nextIncidentEdgeFrom d g = let perm  = g^.embedding+                               (i,j) = lookupIdx perm d+                           in next (perm^?!orbits.ix i) j  +-- | Given a dart d that points into away from vertex v, report the previous dart in the+-- cyclic (counterclockwise) order around v.+--+-- >>> prevIncidentEdgeFrom (Dart (Arc 3) Positive) myGraph+-- Dart (Arc 4) +1+-- >>> showWithData myGraph $ prevIncidentEdgeFrom (Dart (Arc 3) Positive) myGraph+-- (Dart (Arc 4) +1,"e+")+-- >>> showWithData myGraph $ prevIncidentEdgeFrom (Dart (Arc 1) Positive) myGraph+-- (Dart (Arc 2) +1,"c+")+--+-- running time: \(O(1)\)+prevIncidentEdgeFrom     :: Dart s -> PlanarGraph s w v e f -> Dart s+prevIncidentEdgeFrom d g = let perm  = g^.embedding+                               (i,j) = lookupIdx perm d+                           in previous (perm^?!orbits.ix i) j++ -------------------------------------------------------------------------------- -- * Access data @@ -506,6 +585,9 @@   -- | Data corresponding to the endpoints of the dart+--+-- >>> myGraph^.endPointDataOf (Dart (Arc 3) Positive)+-- ("w","v") endPointDataOf   :: Dart s -> Getter (PlanarGraph s w v e f) (v,v) endPointDataOf d = to $ endPointData d @@ -551,3 +633,35 @@                         (g^.rawDartData)                         (g^.vertexData)                         g++++--------------------------------------------------------------------------------++-- myGraph :: PlanarGraph () Primal String String String+-- myGraph = planarGraph [ [ (Dart aA Negative, "a-")+--                             , (Dart aC Positive, "c+")+--                             , (Dart aB Positive, "b+")+--                             , (Dart aA Positive, "a+")+--                             ]+--                           , [ (Dart aE Negative, "e-")+--                             , (Dart aB Negative, "b-")+--                             , (Dart aD Negative, "d-")+--                             , (Dart aG Positive, "g+")+--                             ]+--                           , [ (Dart aE Positive, "e+")+--                             , (Dart aD Positive, "d+")+--                             , (Dart aC Negative, "c-")+--                             ]+--                           , [ (Dart aG Negative, "g-")+--                             ]+--                           ]+--           & vertexData .~ V.fromList ["u","v","w","x"]+--           & faceData   .~ V.fromList ["f_3", "f_infty","f_1","f_2"]+--   where+--     (aA:aB:aC:aD:aE:aG:_) = take 6 [Arc 0..]++-- dart i s = Dart (Arc i) (read s)++-- showWithData     :: HasDataOf s i => s -> i -> (i, DataOf s i)+-- showWithData g i = (i, g^.dataOf i)
src/Data/PlanarGraph/Dual.hs view
@@ -24,7 +24,7 @@ -- >>> :{ -- let dart i s = Dart (Arc i) (read s) --     (aA:aB:aC:aD:aE:aG:_) = take 6 [Arc 0..]---     myGraph :: PlanarGraph () Primal () String ()+--     myGraph :: PlanarGraph () Primal String String String --     myGraph = planarGraph [ [ (Dart aA Negative, "a-") --                             , (Dart aC Positive, "c+") --                             , (Dart aB Positive, "b+")@@ -41,7 +41,10 @@ --                             ] --                           , [ (Dart aG Negative, "g-") --                             ]---                           ]+--                           ] & vertexData .~ V.fromList ["u","v","w","x"]+--                             & faceData   .~ V.fromList ["f_3", "f_infty","f_1","f_2"]+--     showWithData     :: HasDataOf s i => s -> i -> (i, DataOf s i)+--     showWithData g i = (i, g^.dataOf i) -- :} -- --@@ -61,14 +64,17 @@  -- | The face to the left of the dart --+-- -- >>> leftFace (dart 1 "+1") myGraph -- FaceId 1+-- >>> showWithData myGraph $ leftFace (dart 1 "+1") myGraph+-- (FaceId 1,"f_infty") -- >>> leftFace (dart 1 "-1") myGraph -- FaceId 2--- >>> leftFace (dart 2 "+1") myGraph--- FaceId 2--- >>> leftFace (dart 0 "+1") myGraph--- FaceId 0+-- >>> showWithData myGraph $ leftFace (dart 1 "-1") myGraph+-- (FaceId 2,"f_1")+-- >>> showWithData myGraph $ leftFace (dart 0 "+1") myGraph+-- (FaceId 0,"f_3") -- -- running time: \(O(1)\). leftFace     :: Dart s -> PlanarGraph s w v e f -> FaceId s w@@ -77,50 +83,95 @@  -- | The face to the right of the dart --+-- -- >>> rightFace (dart 1 "+1") myGraph -- FaceId 2+-- >>> showWithData myGraph $ rightFace (dart 1 "+1") myGraph+-- (FaceId 2,"f_1") -- >>> rightFace (dart 1 "-1") myGraph -- FaceId 1--- >>> rightFace (dart 2 "+1") myGraph--- FaceId 1--- >>> rightFace (dart 0 "+1") myGraph--- FaceId 1+-- >>> showWithData myGraph $ rightFace (dart 1 "-1") myGraph+-- (FaceId 1,"f_infty")+-- >>> showWithData myGraph $ rightFace (dart 0 "+1") myGraph+-- (FaceId 1,"f_infty") -- -- running time: \(O(1)\). rightFace     :: Dart s -> PlanarGraph s w v e f -> FaceId s w rightFace d g = FaceId . tailOf d $ _dual g  --- | Get the next edge along the face+-- | Get the next edge (in clockwise order) along the face that is to+-- the right of this dart. --+-- >> showWithData myGraph $ nextEdge (dart 1 "+1") myGraph+-- (Dart (Arc 3) -1,"d-")+-- >> showWithData myGraph $ nextEdge (dart 2 "+1") myGraph+-- (Dart (Arc 4) +1,"e+")+-- -- running time: \(O(1)\). nextEdge   :: Dart s -> PlanarGraph s w v e f -> Dart s-nextEdge d = nextIncidentEdge d . _dual+nextEdge d = nextIncidentEdgeFrom d . _dual+  -- prevIncidentEdge (twin d) (_dual g)+  -- where+  --   f = rightFace d g --- | Get the previous edge along the face+-- | Get the previous edge (in clockwise order) along the face that is+-- to the right of this dart. --+-- >>> showWithData myGraph $ prevEdge (dart 1 "+1") myGraph+-- (Dart (Arc 2) -1,"c-")+-- >>> showWithData myGraph $ prevEdge (dart 3 "-1") myGraph+-- (Dart (Arc 1) +1,"b+")+-- -- running time: \(O(1)\).-prevEdge :: Dart s -> PlanarGraph s w v e f -> Dart s-prevEdge d = prevIncidentEdge d . _dual-+prevEdge   :: Dart s -> PlanarGraph s w v e f -> Dart s+prevEdge d = prevIncidentEdgeFrom d . _dual  -- | Gets a dart bounding this face. I.e. a dart d such that the face lies to -- the right of the dart.+--+-- >>> boundaryDart (FaceId $ VertexId 2) myGraph+-- Dart (Arc 1) +1+-- >>> showWithData myGraph $ boundaryDart (FaceId $ VertexId 2) myGraph+-- (Dart (Arc 1) +1,"b+")+-- >>> showWithData myGraph $ boundaryDart (FaceId $ VertexId 1) myGraph+-- (Dart (Arc 2) +1,"c+") boundaryDart   :: FaceId s w -> PlanarGraph s w v e f -> Dart s boundaryDart f = V.head . boundary f--- TODO: make sure that this is indeed to the right. --- | The darts bounding this face, for internal faces in clockwise order, for--- the outer face in counter clockwise order.+-- | The darts bounding this face. The darts are reported in order+-- along the face. This means that for internal faces the darts are+-- reported in *clockwise* order along the boundary, whereas for the+-- outer face the darts are reported in counter clockwise order. --+-- >>> boundary (FaceId $ VertexId 2) myGraph+-- [Dart (Arc 1) +1,Dart (Arc 3) -1,Dart (Arc 2) -1]+-- >>> mapM_ (print . showWithData myGraph) $ boundary (FaceId $ VertexId 2) myGraph+-- (Dart (Arc 1) +1,"b+")+-- (Dart (Arc 3) -1,"d-")+-- (Dart (Arc 2) -1,"c-")+-- >>> boundary (FaceId $ VertexId 1) myGraph+-- [Dart (Arc 2) +1,Dart (Arc 4) +1,Dart (Arc 1) -1,Dart (Arc 0) +1]+-- >>> mapM_ (print . showWithData myGraph) $ boundary (FaceId $ VertexId 1) myGraph+-- (Dart (Arc 2) +1,"c+")+-- (Dart (Arc 4) +1,"e+")+-- (Dart (Arc 1) -1,"b-")+-- (Dart (Arc 0) +1,"a+") -- -- running time: \(O(k)\), where \(k\) is the output size. boundary              :: FaceId s w -> PlanarGraph s w v e f -> V.Vector (Dart s) boundary (FaceId v) g = incidentEdges v $ _dual g ---- | Generates the darts incident to a face, starting with the given dart.+-- | Given a dart d, generates the darts bounding the face that is to+-- the right of the given dart. The darts are reported in order along+-- the face. This means that for internal faces the darts are reported+-- in *clockwise* order along the boundary, whereas for the outer face+-- the darts are reported in counter clockwise order. --+-- >>> mapM_ (print . showWithData myGraph) $ boundary' (dart 1 "+1") myGraph+-- (Dart (Arc 1) +1,"b+")+-- (Dart (Arc 3) -1,"d-")+-- (Dart (Arc 2) -1,"c-") -- -- \(O(k)\), where \(k\) is the number of darts reported boundary'     :: Dart s -> PlanarGraph s w v e f -> V.Vector (Dart s)@@ -132,9 +183,18 @@         f i = let (a,b) = V.splitAt i v  in b <> a  --- | The vertices bounding this face, for internal faces in clockwise order, for--- the outer face in counter clockwise order.+-- | The vertices bounding this face, for internal faces in clockwise+-- order, for the outer face in counter clockwise order. --+-- >>> mapM_ (print . showWithData myGraph) $ boundaryVertices (FaceId $ VertexId 2) myGraph+-- (VertexId 0,"u")+-- (VertexId 1,"v")+-- (VertexId 2,"w")+-- >>> mapM_ (print . showWithData myGraph) $ boundaryVertices (FaceId $ VertexId 1) myGraph+-- (VertexId 0,"u")+-- (VertexId 2,"w")+-- (VertexId 1,"v")+-- (VertexId 0,"u") -- -- running time: \(O(k)\), where \(k\) is the output size. boundaryVertices     :: FaceId s w -> PlanarGraph s w v e f -> V.Vector (VertexId s w)
src/Data/PlanarGraph/IO.hs view
@@ -141,7 +141,9 @@     toOrbit (u,adjU) = concatMap (toDart u) adjU      -- if u = v we have a self-loop, so we add both a positive and a negative dart-    toDart u v = let Just a = findEdge u v oracle+    toDart u v = let a = case findEdge u v oracle of+                           Nothing -> error $ "edge not found? " <> show (u,v)+                           Just a' -> a'                  in case u `compare` v of                       LT -> [Dart (Arc a) Positive]                       EQ -> [Dart (Arc a) Positive, Dart (Arc a) Negative]
src/Data/PlanarGraph/Immutable.hs view
@@ -261,7 +261,8 @@ panic tag msg = error $ "Data.PlanarGraph.Immutable." ++ tag ++ ": " ++ msg  --- $setup+-- Disabled since hashes are not stable across different versions of hashable.+-- // $setup -- -- >>> hash $ pgFromFaces [[0,1,2]] -- 2959979592048325618@@ -375,7 +376,8 @@ -- vertexId :: Vertex -> VertexId -- vertexId (Vertex vId) = vId --- $hidden+-- Disabled since hashes are not stable across different versions of hashable.+-- // $hidden -- -- >>> hash $ pgFromFaces [[0,1,2]] -- 2959979592048325618@@ -419,7 +421,8 @@ vertexHalfEdge (Vertex vId) pg = HalfEdge $ pgVertexEdges pg Vector.! vId  --- $hidden+-- Disabled since hashes are not stable across different versions of hashable.+-- // $hidden -- -- >>> hash $ pgFromFaces [[0,1,2,3],[4,3,2,1]] -- 1711135548958680232@@ -518,7 +521,8 @@       | he == first = nil       | otherwise   = cons he (g (advance he) cons nil) --- $hidden+-- Disabled since hashes are not stable across different versions of hashable.+-- // $hidden -- -- >>> hash $ pgFromFaces [[0,1,2,3],[4,3,2,1]] -- 1711135548958680232@@ -667,7 +671,8 @@ -- halfEdgeId :: HalfEdge -> HalfEdgeId -- halfEdgeId (HalfEdge eId) = eId --- $hidden+-- Disabled since hashes are not stable across different versions of hashable.+-- // $hidden -- -- >>> hash $ pgFromFaces [[0,1,2,3],[4,3,2,1]] -- 1711135548958680232@@ -864,7 +869,8 @@ halfEdgeTipVertex  :: HalfEdge -> PlanarGraph -> Vertex halfEdgeTipVertex e pg = halfEdgeVertex (halfEdgeTwin e) pg --- $hidden+-- Disabled since hashes are not stable across different versions of hashable.+-- // $hidden -- -- >>> hash $ pgFromFaces [[0,1,2]] -- 2959979592048325618
src/Data/PlanarGraph/Mutable.hs view
@@ -111,8 +111,8 @@ data Face s = Face FaceId (PlanarGraph s) | Boundary FaceId (PlanarGraph s)   deriving Eq instance Show (Face s) where-  showsPrec d (Face fId _)     = showString "Face " . shows fId-  showsPrec d (Boundary fId _) = showString "Boundary " . shows fId+  showsPrec _ (Face fId _)     = showString "Face " . shows fId+  showsPrec _ (Boundary fId _) = showString "Boundary " . shows fId  ------------------------------------------------------------------------------- -- Planar graph@@ -139,26 +139,28 @@   <*> newVector nFaces   <*> newVector 0 -{--  For all boundary vertices:-    vertex.half-edge.face == interior-    vertex.half-edge.twin.face == exterior-  Boundary face: 0+-- {-+--   For all boundary vertices:+--     vertex.half-edge.face == interior+--     vertex.half-edge.twin.face == exterior+--   Boundary face: 0 -  create N--}--- | O(n)---   Create a planar graph with N boundary vertices.-new :: Int -> ST s (PlanarGraph s)-new n | n < 0 = panic "new" "Cannot contain negative vertices."-new 0 = empty 0 0 0-new 1 = undefined-new 2 = undefined-new n = pgFromFaces [[0..n-1]]+--   create N+-- -}+-- -- | O(n)+-- --   Create a planar graph with N boundary vertices.+-- new :: Int -> ST s (PlanarGraph s)+-- new n | n < 0 = panic "new" "Cannot contain negative vertices."+-- new 0 = empty 0 0 0+-- new 1 = undefined+-- new 2 = undefined+-- new n = pgFromFaces [[0..n-1]]  -- $setup -- -- >>> import Control.Monad.ST++-- Disabled since hashes are not stable across different versions of hashable. -- >>> runST $ pgFromFaces [[0,1,2]] >>= pgHash -- 2959979592048325618 -- >>> runST $ pgFromFaces [[0,1,2,3]] >>= pgHash@@ -320,12 +322,12 @@ -- vertexAdjacentVertices :: Vertex -> PlanarGraph -> [Vertex] -- vertexAdjacentFaces :: Vertex -> PlanarGraph -> [Face] --- O(1), internal function.-vertexNew :: PlanarGraph s -> ST s (Vertex s)-vertexNew pg = do-  vId <- readSTRef (pgNextVertexId pg)-  writeSTRef (pgNextVertexId pg) (vId+1)-  return (Vertex vId pg)+-- -- O(1), internal function.+-- vertexNew :: PlanarGraph s -> ST s (Vertex s)+-- vertexNew pg = do+--   vId <- readSTRef (pgNextVertexId pg)+--   writeSTRef (pgNextVertexId pg) (vId+1)+--   return (Vertex vId pg)  vertexSetHalfEdge :: Vertex s -> HalfEdge s -> ST s () vertexSetHalfEdge (Vertex vId pg) (HalfEdge eId pg') = eqCheck "vertexSetHalfEdge" pg pg' $@@ -346,9 +348,9 @@ edgeFromHalfEdge :: HalfEdge s -> Edge s edgeFromHalfEdge (HalfEdge he pg) = Edge (he `div` 2) pg --- | O(1)-edgeToHalfEdges :: Edge s -> (HalfEdge s, HalfEdge s)-edgeToHalfEdges (Edge e pg) = (HalfEdge (e*2) pg, HalfEdge (e*2+1) pg)+-- -- | O(1)+-- edgeToHalfEdges :: Edge s -> (HalfEdge s, HalfEdge s)+-- edgeToHalfEdges (Edge e pg) = (HalfEdge (e*2) pg, HalfEdge (e*2+1) pg)  ------------------------------------------------------------------------------- -- Half-edges@@ -357,9 +359,9 @@ halfEdgePlanarGraph :: HalfEdge s -> PlanarGraph s halfEdgePlanarGraph (HalfEdge _ pg) = pg --- | O(1)-halfEdgeIsValid :: HalfEdge s -> Bool-halfEdgeIsValid (HalfEdge eId _) = eId >= 0+-- -- | O(1)+-- halfEdgeIsValid :: HalfEdge s -> Bool+-- halfEdgeIsValid (HalfEdge eId _) = eId >= 0  -- | O(1) halfEdgeFromId :: HalfEdgeId -> PlanarGraph s -> HalfEdge s
src/Data/Range.hs view
@@ -208,6 +208,7 @@  type instance IntersectionOf (Range a) (Range a) = [ NoIntersection, Range a] +instance Ord a => Range a `HasIntersectionWith` Range a instance Ord a => Range a `IsIntersectableWith` Range a where    nonEmptyIntersection = defaultNonEmptyIntersection
src/Data/Set/Util.hs view
@@ -136,5 +136,5 @@   -test = queryBy cmpS Set.lookupGE (S "22") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]+-- test = queryBy cmpS Set.lookupGE (S "22") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"] -- test = succBy cmpS (S "22") $ fromListBy cmpS [S "a" , S "bbb" , S "ddddddd"]
test/Algorithms/DivideAndConquerSpec.hs view
@@ -1,10 +1,11 @@ module Algorithms.DivideAndConquerSpec where  import Algorithms.DivideAndConquer- import           Test.Hspec import           Test.QuickCheck import qualified Data.List as List++--------------------------------------------------------------------------------  spec = describe "divide and conquer strategy tests" $ do          it "mergeSort" $ property $
+ test/Algorithms/LogarithmicMethodSpec.hs view
@@ -0,0 +1,45 @@+module Algorithms.LogarithmicMethodSpec where++import           Algorithms.LogarithmicMethod+import           Data.List.NonEmpty (NonEmpty(..))+import qualified Data.List.NonEmpty as NonEmpty+import           Data.Maybe (mapMaybe)+import           Data.Semigroup+import           Data.Semigroup.Foldable+import           Data.List.Util+import           Test.Hspec+import           Test.QuickCheck++--------------------------------------------------------------------------------++spec :: Spec+spec = describe "Logarithmic method successor test" $ do+         it "successor test" $ property $+           \q (xs :: [Int]) ->+             successor q (fromList xs)+             `shouldBe`+             minimum1 [ x | x <- xs, x >= q]++         it "merge test" $ property $+           \q (xs :: [Int]) (ys :: [Int]) ->+             successor q ((fromList xs) <> (fromList ys))+             `shouldBe`+             successor q (fromList $ xs <> ys)+++newtype DummySucc a = Dummy (NonEmpty a)+  deriving (Show,Eq,Functor,Foldable,Foldable1,Traversable)++instance Ord a => LogarithmicMethodDS DummySucc a where+  build = Dummy . NonEmpty.sort++successor'              :: Ord a => a -> DummySucc a -> Option (Min a)+successor' q (Dummy xs) = case NonEmpty.dropWhile (< q) xs of+                            []    -> Option Nothing+                            (s:_) -> Option (Just (Min s))++successor   :: Ord a => a -> InsertionOnly DummySucc a -> Maybe a+successor q = fmap getMin . getOption . queryWith (successor' q)++fromList :: Ord a => [a] -> InsertionOnly DummySucc a+fromList = foldr insert empty