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