package grenier
A collection of various algorithms in OCaml
Install
Dune Dependency
Authors
Maintainers
Sources
grenier-0.15.tbz
sha256=dec7f84b9e93d5825f10c7dea84d5a74d7365ede45664ae63c26b5e8045c1c44
sha512=b8aa1569c2e24b89674d1b34de34cd1798896bb6a53aa5a1287f68cee880125e6b687f66ad73da9069a01cc3ece1f0684f48328b099d43529bff736b772c8fd8
doc/src/grenier.fastdom/fastdom.ml.html
Source file fastdom.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
(** Metadata associated to a graph node (of type 'a) *) type 'a t = { node: 'a; (** Node the metadata applies to *) mutable index: int; (** Index of the node in postorder traversal: [-1] for invalid or unvisited nodes [max_int] for a marked node during traversal [n >= 0] for a valid and visited node *) mutable predecessors: 'a t list; (** List of node predecessors (used temporarily) *) mutable dom: 'a t; (** Dominator of this node *) } (** Public accessors *) let node t = t.node let dominator t = t.dom let postorder_index t = t.index let predecessors t = t.predecessors (* We use [-1] index for identifying invalid or unvisited nodes *) let is_valid node = node.index >= 0 (* Intersect set of nodes, using the encoding defined in the paper *) let rec maximize ~target node = (*Printf.eprintf "maximize(%d,%d)\n" node.index target;*) if node.index < target then maximize ~target node.dom else node let rec intersect b1 b2 = if b1 != b2 then let b1 = maximize ~target:b2.index b1 in let b2 = maximize ~target:b1.index b2 in intersect b1 b2 else b1 (* Intersect immediate dominators *) let rec update_idom = function | [] -> None | x :: xs -> if is_valid x.dom then let isect acc p = if is_valid p.dom then intersect p acc else acc in Some (List.fold_left isect x xs) else update_idom xs (* Traverse and update dominators until a fixpoint is reached *) let dominator_fixpoint nodes count = let changed = ref true in while !changed do changed := false; for i = count - 2 downto 0 do let node = nodes.(i) in match update_idom node.predecessors with | None -> () | Some dom -> if dom != node.dom then (node.dom <- dom; changed := true) done done (** Representation of a graph with nodes of type 'a *) type 'a graph = { memoize: 'b. ('a -> 'b) -> ('a -> 'b); (** Memoize a function on nodes *) successors: 'b. ('b -> 'a -> 'b) -> 'b -> 'a -> 'b; (** Fold over successors of a node *) } (* Compute a postorder traversal: - associate tags to each node of a graph - number the tags - return an array of all tags in postorder *) let postorder (type a) (graph : a graph) (start : a) = (* Sentinel value for undefined nodes *) let rec undefined = {node = start; index = -1; predecessors = []; dom = undefined} in (* A function to associate a `'a t` tag to each node of the graph *) let tag_of = let mk node = {node; index = -1; predecessors = []; dom = undefined} in graph.memoize mk in (* A vector to record all the tags *) let buffer = ref [|undefined; undefined|] in let mark tag = tag.index <- max_int in let record tag index = tag.index <- index; if index >= Array.length !buffer then ( let buffer' = Array.make (index * 2) undefined in Array.blit !buffer 0 buffer' 0 (Array.length !buffer); buffer := buffer'; ); assert ((!buffer).(index) == undefined); (!buffer).(index) <- tag; in (* Visit a node in DFS, record post-order index *) let rec process_tag idx tag = if tag.index = -1 then ( mark tag; let idx = graph.successors (process_successor tag) idx tag.node in record tag idx; (idx + 1) ) else idx (* Record predecessors when visiting successors *) and process_successor self index succ = let tag = tag_of succ in tag.predecessors <- self :: tag.predecessors; process_tag index tag in (* Begin post-order visit *) let start = tag_of start in start.dom <- start; let count = process_tag 0 start in (tag_of, Array.sub !buffer 0 count) (* dominance = postorder traversal & dominators fixpoint *) let dominance (type a) (graph : a graph) (start : a) = let tag_of, postorder = postorder graph start in (*Printf.eprintf "postorder: %d nodes\n" (Array.length postorder); Array.iteri (fun i tag -> Printf.eprintf "postorder[%d]: node=%d index=%d |predecessors|=%d dominator=%d\n" i (Obj.magic tag.node) tag.index (List.length tag.predecessors) tag.dom.index; ) postorder;*) dominator_fixpoint postorder (Array.length postorder); (postorder, tag_of) let is_reachable = is_valid
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>