1{-# OPTIONS_GHC -funbox-strict-fields #-}
2{-# LANGUAGE BangPatterns #-}
17{- This is based on the following implementations:
19 - https://hackage.haskell.org/package/union-find-0.2/docs/src/Data-UnionFind-IO.html
20 - http://yann.regis-gianas.org/public/mini/code_UnionFind.html
22It seems like the OCaml one came first, but I am not sure.
24Compared to the Haskell implementation, the major changes here include:
26 1. No more reallocating PointInfo when changing the weight
27 2. Using the strict modifyIORef
32import Control.Monad ( when )
33import Data.IORef (IORef, modifyIORef', newIORef, readIORef, writeIORef)
34import Data.Word (Word32)
42 Pt (IORef (PointInfo a))
47 = Info {-# UNPACK #-} !(IORef Word32) {-# UNPACK #-} !(IORef a)
48 | Link {-# UNPACK #-} !(Point a)
55fresh :: a -> IO (Point a)
57 do weight <- newIORef 1
58 desc <- newIORef value
59 link <- newIORef (Info weight desc)
63repr :: Point a -> IO (Point a)
65 do pInfo <- readIORef ref
70 Link point1@(Pt ref1) ->
71 do point2 <- repr point1
72 when (point2 /= point1) $
73 do pInfo1 <- readIORef ref1
78descriptor :: Point a -> IO a
79descriptor point@(Pt ref) =
80 do pInfo <- readIORef ref
86 do link' <- readIORef ref1
92 descriptor =<< repr point
95setDescriptor :: Point a -> a -> IO ()
96setDescriptor point@(Pt ref) newDesc =
97 do pInfo <- readIORef ref
100 writeIORef descRef newDesc
103 do link' <- readIORef ref1
106 writeIORef descRef newDesc
109 do newPoint <- repr point
110 setDescriptor newPoint newDesc
113modifyDescriptor :: Point a -> (a -> a) -> IO ()
114modifyDescriptor point@(Pt ref) func =
115 do pInfo <- readIORef ref
118 modifyIORef' descRef func
121 do link' <- readIORef ref1
124 modifyIORef' descRef func
127 do newPoint <- repr point
128 modifyDescriptor newPoint func
131union :: Point a -> Point a -> a -> IO ()
133 do point1@(Pt ref1) <- repr p1
134 point2@(Pt ref2) <- repr p2
136 Info w1 d1 <- readIORef ref1
137 Info w2 d2 <- readIORef ref2
140 then writeIORef d1 newDesc
142 weight1 <- readIORef w1
143 weight2 <- readIORef w2
145 let !newWeight = weight1 + weight2
147 if weight1 >= weight2
149 do writeIORef ref2 (Link point1)
150 writeIORef w1 newWeight
151 writeIORef d1 newDesc
153 do writeIORef ref1 (Link point2)
154 writeIORef w2 newWeight
155 writeIORef d2 newDesc
158equivalent :: Point a -> Point a -> IO Bool
165redundant :: Point a -> IO Bool
167 do pInfo <- readIORef ref
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list