1 /* ========================================================================= */ 2 /* === AMD_post_tree ======================================================= */ 3 /* ========================================================================= */ 4 5 /* ------------------------------------------------------------------------- */ 6 /* AMD, Copyright (c) Timothy A. Davis, */ 7 /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ 8 /* email: DrTimothyAldenDavis@gmail.com */ 9 /* ------------------------------------------------------------------------- */ 10 11 /* Post-ordering of a supernodal elimination tree. */ 12 13 module amd_post_tree; 14 15 nothrow @nogc extern(C): 16 17 import amd_internal; 18 19 version(NDEBUG){ 20 Int AMD_post_tree 21 ( 22 Int root, /* root of the tree */ 23 Int k, /* start numbering at k */ 24 Int * Child, /* input argument of size nn, undefined on 25 * output. Child [i] is the head of a link 26 * list of all nodes that are children of node 27 * i in the tree. */ 28 const Int * Sibling, /* input argument of size nn, not modified. 29 * If f is a node in the link list of the 30 * children of node i, then Sibling [f] is the 31 * next child of node i. 32 */ 33 Int * Order, /* output order, of size nn. Order [i] = k 34 * if node i is the kth node of the reordered 35 * tree. */ 36 Int * Stack, /* workspace of size nn */ 37 ) 38 { 39 Int f, head, h, i ; 40 Int nn = 0; // fake value, ignored in ASSERTs 41 42 version (none){ 43 /* --------------------------------------------------------------------- */ 44 /* recursive version (Stack [ ] is not used): */ 45 /* --------------------------------------------------------------------- */ 46 47 /* this is simple, but can caouse stack overflow if nn is large */ 48 i = root ; 49 for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 50 { 51 k = AMD_post_tree (f, k, Child, Sibling, Order, Stack, nn) ; 52 } 53 Order [i] = k++ ; 54 return (k) ; 55 } // none 56 57 /* --------------------------------------------------------------------- */ 58 /* non-recursive version, using an explicit stack */ 59 /* --------------------------------------------------------------------- */ 60 61 /* push root on the stack */ 62 head = 0 ; 63 Stack [0] = root ; 64 65 while (head >= 0) 66 { 67 /* get head of stack */ 68 ASSERT (head < nn) ; 69 i = Stack [head] ; 70 AMD_DEBUG1 ("head of stack "~ID~" \n", i); 71 ASSERT (i >= 0 && i < nn) ; 72 73 if (Child [i] != EMPTY) 74 { 75 /* the children of i are not yet ordered */ 76 /* push each child onto the stack in reverse order */ 77 /* so that small ones at the head of the list get popped first */ 78 /* and the biggest one at the end of the list gets popped last */ 79 for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 80 { 81 head++ ; 82 ASSERT (head < nn) ; 83 ASSERT (f >= 0 && f < nn) ; 84 } 85 h = head ; 86 ASSERT (head < nn) ; 87 for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 88 { 89 ASSERT (h > 0) ; 90 Stack [h--] = f ; 91 AMD_DEBUG1 ("push "~ID~" on stack\n", f); 92 ASSERT (f >= 0 && f < nn) ; 93 } 94 ASSERT (Stack [h] == i) ; 95 96 /* delete child list so that i gets ordered next time we see it */ 97 Child [i] = EMPTY ; 98 } 99 else 100 { 101 /* the children of i (if there were any) are already ordered */ 102 /* remove i from the stack and order it. Front i is kth front */ 103 head-- ; 104 AMD_DEBUG1 ("pop "~ID~" order "~ID~"\n", i, k); 105 Order [i] = k++ ; 106 ASSERT (k <= nn) ; 107 } 108 } 109 return (k) ; 110 } 111 112 } else { // NDEBUG 113 Int AMD_post_tree 114 ( 115 Int root, /* root of the tree */ 116 Int k, /* start numbering at k */ 117 Int * Child, /* input argument of size nn, undefined on 118 * output. Child [i] is the head of a link 119 * list of all nodes that are children of node 120 * i in the tree. */ 121 const Int * Sibling, /* input argument of size nn, not modified. 122 * If f is a node in the link list of the 123 * children of node i, then Sibling [f] is the 124 * next child of node i. 125 */ 126 Int * Order, /* output order, of size nn. Order [i] = k 127 * if node i is the kth node of the reordered 128 * tree. */ 129 Int * Stack, /* workspace of size nn */ 130 Int nn /* nodes are in the range 0..nn-1. */ 131 ) 132 { 133 Int f, head, h, i ; 134 135 version (none){ 136 /* --------------------------------------------------------------------- */ 137 /* recursive version (Stack [ ] is not used): */ 138 /* --------------------------------------------------------------------- */ 139 140 /* this is simple, but can caouse stack overflow if nn is large */ 141 i = root ; 142 for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 143 { 144 k = AMD_post_tree (f, k, Child, Sibling, Order, Stack, nn) ; 145 } 146 Order [i] = k++ ; 147 return (k) ; 148 } // none 149 150 /* --------------------------------------------------------------------- */ 151 /* non-recursive version, using an explicit stack */ 152 /* --------------------------------------------------------------------- */ 153 154 /* push root on the stack */ 155 head = 0 ; 156 Stack [0] = root ; 157 158 while (head >= 0) 159 { 160 /* get head of stack */ 161 ASSERT (head < nn) ; 162 i = Stack [head] ; 163 AMD_DEBUG1 ("head of stack "~ID~" \n", i) ; 164 ASSERT (i >= 0 && i < nn) ; 165 166 if (Child [i] != EMPTY) 167 { 168 /* the children of i are not yet ordered */ 169 /* push each child onto the stack in reverse order */ 170 /* so that small ones at the head of the list get popped first */ 171 /* and the biggest one at the end of the list gets popped last */ 172 for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 173 { 174 head++ ; 175 ASSERT (head < nn) ; 176 ASSERT (f >= 0 && f < nn) ; 177 } 178 h = head ; 179 ASSERT (head < nn) ; 180 for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 181 { 182 ASSERT (h > 0) ; 183 Stack [h--] = f ; 184 AMD_DEBUG1 ("push "~ID~" on stack\n", f) ; 185 ASSERT (f >= 0 && f < nn) ; 186 } 187 ASSERT (Stack [h] == i) ; 188 189 /* delete child list so that i gets ordered next time we see it */ 190 Child [i] = EMPTY ; 191 } 192 else 193 { 194 /* the children of i (if there were any) are already ordered */ 195 /* remove i from the stack and order it. Front i is kth front */ 196 head-- ; 197 AMD_DEBUG1 ("pop "~ID~" order "~ID~"\n", i, k) ; 198 Order [i] = k++ ; 199 ASSERT (k <= nn) ; 200 } 201 202 AMD_DEBUG1 ("\nStack:"); 203 for (h = head ; h >= 0 ; h--) 204 { 205 Int j = Stack [h] ; 206 AMD_DEBUG1 (" "~ID, j) ; 207 ASSERT (j >= 0 && j < nn) ; 208 } 209 AMD_DEBUG1 ("\n\n"); 210 ASSERT (head < nn) ; 211 } 212 return (k) ; 213 } 214 215 } // NDEBUG