1 /* ========================================================================= */ 2 /* === AMD_postorder ======================================================= */ 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 /* Perform a postordering (via depth-first search) of an assembly tree. */ 12 13 module amd_postorder; 14 15 nothrow @nogc extern(C): 16 17 import amd_internal; 18 import amd_post_tree; 19 20 void AMD_postorder 21 ( 22 /* inputs, not modified on output: */ 23 Int nn, /* nodes are in the range 0..nn-1 */ 24 Int * Parent, /* Parent [j] is the parent of j, or EMPTY if root */ 25 Int * Nv, /* Nv [j] > 0 number of pivots represented by node j, 26 * or zero if j is not a node. */ 27 Int * Fsize, /* Fsize [j]: size of node j */ 28 29 /* output, not defined on input: */ 30 Int * Order, /* output post-order */ 31 32 /* workspaces of size nn: */ 33 Int * Child, 34 Int * Sibling, 35 Int * Stack 36 ) 37 { 38 Int i, j, k, parent, frsize, f, fprev, maxfrsize, bigfprev, bigf, fnext ; 39 40 for (j = 0 ; j < nn ; j++) 41 { 42 Child [j] = EMPTY ; 43 Sibling [j] = EMPTY ; 44 } 45 46 /* --------------------------------------------------------------------- */ 47 /* place the children in link lists - bigger elements tend to be last */ 48 /* --------------------------------------------------------------------- */ 49 50 for (j = nn-1 ; j >= 0 ; j--) 51 { 52 if (Nv [j] > 0) 53 { 54 /* this is an element */ 55 parent = Parent [j] ; 56 if (parent != EMPTY) 57 { 58 /* place the element in link list of the children its parent */ 59 /* bigger elements will tend to be at the end of the list */ 60 Sibling [j] = Child [parent] ; 61 Child [parent] = j ; 62 } 63 } 64 } 65 version(NDEBUG){} 66 else { 67 68 { 69 Int nels, ff, nchild ; 70 AMD_DEBUG1 ("\n\n================================ AMD_postorder:\n"); 71 nels = 0 ; 72 for (j = 0 ; j < nn ; j++) 73 { 74 if (Nv [j] > 0) 75 { 76 AMD_DEBUG1 ( ""~ID~" : nels "~ID~" npiv "~ID~" size "~ID~" parent "~ID~" maxfr "~ID~"\n", j, nels,Nv [j], Fsize [j], Parent [j], Fsize [j]) ; 77 /* this is an element */ 78 /* dump the link list of children */ 79 nchild = 0 ; 80 AMD_DEBUG1 (" Children: ") ; 81 for (ff = Child [j] ; ff != EMPTY ; ff = Sibling [ff]) 82 { 83 AMD_DEBUG1 (ID~" ", ff) ; 84 ASSERT (Parent [ff] == j) ; 85 nchild++ ; 86 ASSERT (nchild < nn) ; 87 } 88 AMD_DEBUG1 ("\n") ; 89 parent = Parent [j] ; 90 if (parent != EMPTY) 91 { 92 ASSERT (Nv [parent] > 0) ; 93 } 94 nels++ ; 95 } 96 } 97 } 98 AMD_DEBUG1 ("\n\nGo through the children of each node, and put\nthe biggest child last in each list:\n") ; 99 } // !NDEBUG 100 101 /* --------------------------------------------------------------------- */ 102 /* place the largest child last in the list of children for each node */ 103 /* --------------------------------------------------------------------- */ 104 105 for (i = 0 ; i < nn ; i++) 106 { 107 if (Nv [i] > 0 && Child [i] != EMPTY) 108 { 109 110 version(NDEBUG){} 111 else { 112 Int nchild ; 113 AMD_DEBUG1 ("Before partial sort, element "~ID~"\n", i); 114 nchild = 0 ; 115 for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 116 { 117 ASSERT (f >= 0 && f < nn) ; 118 AMD_DEBUG1 (" f: "~ID~" size: "~ID~"\n", f, Fsize [f]) ; 119 nchild++ ; 120 ASSERT (nchild <= nn) ; 121 } 122 } // !NDEBUG 123 124 /* find the biggest element in the child list */ 125 fprev = EMPTY ; 126 maxfrsize = EMPTY ; 127 bigfprev = EMPTY ; 128 bigf = EMPTY ; 129 for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 130 { 131 ASSERT (f >= 0 && f < nn) ; 132 frsize = Fsize [f] ; 133 if (frsize >= maxfrsize) 134 { 135 /* this is the biggest seen so far */ 136 maxfrsize = frsize ; 137 bigfprev = fprev ; 138 bigf = f ; 139 } 140 fprev = f ; 141 } 142 ASSERT (bigf != EMPTY) ; 143 144 fnext = Sibling [bigf] ; 145 146 AMD_DEBUG1 ("bigf "~ID~" maxfrsize "~ID~" bigfprev "~ID~" fnext "~ID~" fprev " ~ID~"\n", bigf, maxfrsize, bigfprev, fnext, fprev) ; 147 148 if (fnext != EMPTY) 149 { 150 /* if fnext is EMPTY then bigf is already at the end of list */ 151 152 if (bigfprev == EMPTY) 153 { 154 /* delete bigf from the element of the list */ 155 Child [i] = fnext ; 156 } 157 else 158 { 159 /* delete bigf from the middle of the list */ 160 Sibling [bigfprev] = fnext ; 161 } 162 163 /* put bigf at the end of the list */ 164 Sibling [bigf] = EMPTY ; 165 ASSERT (Child [i] != EMPTY) ; 166 ASSERT (fprev != bigf) ; 167 ASSERT (fprev != EMPTY) ; 168 Sibling [fprev] = bigf ; 169 } 170 171 version(NDEBUG){} 172 else { 173 AMD_DEBUG1 ("After partial sort, element "~ID~"\n", i) ; 174 for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) 175 { 176 ASSERT (f >= 0 && f < nn) ; 177 AMD_DEBUG1 (" "~ID~" "~ID~"\n", f, Fsize [f]) ; 178 ASSERT (Nv [f] > 0) ; 179 nchild-- ; 180 } 181 ASSERT (nchild == 0) ; 182 } // !NDEBUG 183 184 } 185 } 186 187 /* --------------------------------------------------------------------- */ 188 /* postorder the assembly tree */ 189 /* --------------------------------------------------------------------- */ 190 191 for (i = 0 ; i < nn ; i++) 192 { 193 Order [i] = EMPTY ; 194 } 195 196 k = 0 ; 197 198 for (i = 0 ; i < nn ; i++) 199 { 200 if (Parent [i] == EMPTY && Nv [i] > 0) 201 { 202 version(NDEBUG){ 203 AMD_DEBUG1 ("Root of assembly tree "~ID~"\n", i) ; 204 k = AMD_post_tree (i, k, Child, Sibling, Order, Stack) ; 205 } 206 else { 207 AMD_DEBUG1 ("Root of assembly tree "~ID~"\n", i) ; 208 k = AMD_post_tree (i, k, Child, Sibling, Order, Stack, nn) ; 209 } // NDEBUG 210 } 211 } 212 }