module Data.Graph.Inductive.Query.Dominators (
dom,
iDom
) where
import Data.Array
import Data.Graph.Inductive.Graph
import Data.Graph.Inductive.Query.DFS
import Data.IntMap (IntMap)
import qualified Data.IntMap as I
import Data.Tree (Tree (..))
import qualified Data.Tree as T
{-# ANN iDom "HLint: ignore Use ***" #-}
iDom :: (Graph gr) => gr a b -> Node -> [(Node,Node)]
iDom :: forall (gr :: * -> * -> *) a b.
Graph gr =>
gr a b -> Node' -> [(Node', Node')]
iDom gr a b
g Node'
root = let (IDom
result, IDom
toNode, FromNode
_) = forall (gr :: * -> * -> *) a b.
Graph gr =>
gr a b -> Node' -> (IDom, IDom, FromNode)
idomWork gr a b
g Node'
root
in forall a b. (a -> b) -> [a] -> [b]
map (\(Node'
a, Node'
b) -> (IDom
toNode forall i e. Ix i => Array i e -> i -> e
! Node'
a, IDom
toNode forall i e. Ix i => Array i e -> i -> e
! Node'
b)) (forall i e. Ix i => Array i e -> [(i, e)]
assocs IDom
result)
dom :: (Graph gr) => gr a b -> Node -> [(Node,[Node])]
dom :: forall (gr :: * -> * -> *) a b.
Graph gr =>
gr a b -> Node' -> [(Node', [Node'])]
dom gr a b
g Node'
root = let
(IDom
iD, IDom
toNode, FromNode
fromNode) = forall (gr :: * -> * -> *) a b.
Graph gr =>
gr a b -> Node' -> (IDom, IDom, FromNode)
idomWork gr a b
g Node'
root
dom' :: Array Node' [Node']
dom' = IDom -> IDom -> Array Node' [Node']
getDom IDom
toNode IDom
iD
nodes' :: [Node']
nodes' = forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [Node']
nodes gr a b
g
rest :: [Node']
rest = forall a. IntMap a -> [Node']
I.keys (forall a. (a -> Bool) -> IntMap a -> IntMap a
I.filter (-Node'
1 forall a. Eq a => a -> a -> Bool
==) FromNode
fromNode)
in
[(IDom
toNode forall i e. Ix i => Array i e -> i -> e
! Node'
i, Array Node' [Node']
dom' forall i e. Ix i => Array i e -> i -> e
! Node'
i) | Node'
i <- forall a. Ix a => (a, a) -> [a]
range (forall i e. Array i e -> (i, i)
bounds Array Node' [Node']
dom')] forall a. [a] -> [a] -> [a]
++
[(Node'
n, [Node']
nodes') | Node'
n <- [Node']
rest]
type Node' = Int
type IDom = Array Node' Node'
type Preds = Array Node' [Node']
type ToNode = Array Node' Node
type FromNode = IntMap Node'
idomWork :: (Graph gr) => gr a b -> Node -> (IDom, ToNode, FromNode)
idomWork :: forall (gr :: * -> * -> *) a b.
Graph gr =>
gr a b -> Node' -> (IDom, IDom, FromNode)
idomWork gr a b
g Node'
root = let
trees :: [Tree Node']
trees@(~[Tree Node'
tree]) = forall (gr :: * -> * -> *) a b.
Graph gr =>
[Node'] -> gr a b -> [Tree Node']
dff [Node'
root] gr a b
g
(Node'
s, Tree Node'
ntree) = forall a. Node' -> Tree a -> (Node', Tree Node')
numberTree Node'
0 Tree Node'
tree
iD0 :: IDom
iD0 = forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
array (Node'
1, Node'
sforall a. Num a => a -> a -> a
-Node'
1) (forall a. [a] -> [a]
tail forall a b. (a -> b) -> a -> b
$ forall a. a -> Tree a -> [(a, a)]
treeEdges (-Node'
1) Tree Node'
ntree)
fromNode :: FromNode
fromNode = forall a. (a -> a -> a) -> IntMap a -> IntMap a -> IntMap a
I.unionWith forall a b. a -> b -> a
const (forall a. [(Node', a)] -> IntMap a
I.fromList (forall a b. [a] -> [b] -> [(a, b)]
zip (forall a. Tree a -> [a]
T.flatten Tree Node'
tree) (forall a. Tree a -> [a]
T.flatten Tree Node'
ntree))) (forall a. [(Node', a)] -> IntMap a
I.fromList (forall a b. [a] -> [b] -> [(a, b)]
zip (forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [Node']
nodes gr a b
g) (forall a. a -> [a]
repeat (-Node'
1))))
toNode :: IDom
toNode = forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
array (Node'
0, Node'
sforall a. Num a => a -> a -> a
-Node'
1) (forall a b. [a] -> [b] -> [(a, b)]
zip (forall a. Tree a -> [a]
T.flatten Tree Node'
ntree) (forall a. Tree a -> [a]
T.flatten Tree Node'
tree))
preds :: Array Node' [Node']
preds = forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
array (Node'
1, Node'
sforall a. Num a => a -> a -> a
-Node'
1) [(Node'
i, forall a. (a -> Bool) -> [a] -> [a]
filter (forall a. Eq a => a -> a -> Bool
/= -Node'
1) (forall a b. (a -> b) -> [a] -> [b]
map (FromNode
fromNode forall a. IntMap a -> Node' -> a
I.!)
(forall (gr :: * -> * -> *) a b.
Graph gr =>
gr a b -> Node' -> [Node']
pre gr a b
g (IDom
toNode forall i e. Ix i => Array i e -> i -> e
! Node'
i)))) | Node'
i <- [Node'
1..Node'
sforall a. Num a => a -> a -> a
-Node'
1]]
iD :: IDom
iD = forall a. Eq a => (a -> a) -> a -> a
fixEq (Array Node' [Node'] -> IDom -> IDom
refineIDom Array Node' [Node']
preds) IDom
iD0
in
if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Tree Node']
trees then forall a. HasCallStack => [Char] -> a
error [Char]
"Dominators.idomWork: root not in graph"
else (IDom
iD, IDom
toNode, FromNode
fromNode)
refineIDom :: Preds -> IDom -> IDom
refineIDom :: Array Node' [Node'] -> IDom -> IDom
refineIDom Array Node' [Node']
preds IDom
iD = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 (IDom -> Node' -> Node' -> Node'
intersect IDom
iD)) Array Node' [Node']
preds
intersect :: IDom -> Node' -> Node' -> Node'
intersect :: IDom -> Node' -> Node' -> Node'
intersect IDom
iD Node'
a Node'
b = case Node'
a forall a. Ord a => a -> a -> Ordering
`compare` Node'
b of
Ordering
LT -> IDom -> Node' -> Node' -> Node'
intersect IDom
iD Node'
a (IDom
iD forall i e. Ix i => Array i e -> i -> e
! Node'
b)
Ordering
EQ -> Node'
a
Ordering
GT -> IDom -> Node' -> Node' -> Node'
intersect IDom
iD (IDom
iD forall i e. Ix i => Array i e -> i -> e
! Node'
a) Node'
b
getDom :: ToNode -> IDom -> Array Node' [Node]
getDom :: IDom -> IDom -> Array Node' [Node']
getDom IDom
toNode IDom
iD = let
res :: Array Node' [Node']
res = forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
array (Node'
0, forall a b. (a, b) -> b
snd (forall i e. Array i e -> (i, i)
bounds IDom
iD)) ((Node'
0, [IDom
toNode forall i e. Ix i => Array i e -> i -> e
! Node'
0]) forall a. a -> [a] -> [a]
:
[(Node'
i, IDom
toNode forall i e. Ix i => Array i e -> i -> e
! Node'
i forall a. a -> [a] -> [a]
: Array Node' [Node']
res forall i e. Ix i => Array i e -> i -> e
! (IDom
iD forall i e. Ix i => Array i e -> i -> e
! Node'
i)) | Node'
i <- forall a. Ix a => (a, a) -> [a]
range (forall i e. Array i e -> (i, i)
bounds IDom
iD)])
in
Array Node' [Node']
res
numberTree :: Node' -> Tree a -> (Node', Tree Node')
numberTree :: forall a. Node' -> Tree a -> (Node', Tree Node')
numberTree Node'
n (Node a
_ [Tree a]
ts) = let (Node'
n', [Tree Node']
ts') = forall a. Node' -> [Tree a] -> (Node', [Tree Node'])
numberForest (Node'
nforall a. Num a => a -> a -> a
+Node'
1) [Tree a]
ts
in (Node'
n', forall a. a -> [Tree a] -> Tree a
Node Node'
n [Tree Node']
ts')
numberForest :: Node' -> [Tree a] -> (Node', [Tree Node'])
numberForest :: forall a. Node' -> [Tree a] -> (Node', [Tree Node'])
numberForest Node'
n [] = (Node'
n, [])
numberForest Node'
n (Tree a
t:[Tree a]
ts) = let (Node'
n', Tree Node'
t') = forall a. Node' -> Tree a -> (Node', Tree Node')
numberTree Node'
n Tree a
t
(Node'
n'', [Tree Node']
ts') = forall a. Node' -> [Tree a] -> (Node', [Tree Node'])
numberForest Node'
n' [Tree a]
ts
in (Node'
n'', Tree Node'
t'forall a. a -> [a] -> [a]
:[Tree Node']
ts')
treeEdges :: a -> Tree a -> [(a,a)]
treeEdges :: forall a. a -> Tree a -> [(a, a)]
treeEdges a
a (Node a
b [Tree a]
ts) = (a
b,a
a) forall a. a -> [a] -> [a]
: forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall a. a -> Tree a -> [(a, a)]
treeEdges a
b) [Tree a]
ts
fixEq :: (Eq a) => (a -> a) -> a -> a
fixEq :: forall a. Eq a => (a -> a) -> a -> a
fixEq a -> a
f a
v | a
v' forall a. Eq a => a -> a -> Bool
== a
v = a
v
| Bool
otherwise = forall a. Eq a => (a -> a) -> a -> a
fixEq a -> a
f a
v'
where v' :: a
v' = a -> a
f a
v