alpar@1
|
1 |
/* ========================================================================= */
|
alpar@1
|
2 |
/* === AMD_post_tree ======================================================= */
|
alpar@1
|
3 |
/* ========================================================================= */
|
alpar@1
|
4 |
|
alpar@1
|
5 |
/* ------------------------------------------------------------------------- */
|
alpar@1
|
6 |
/* AMD, Copyright (c) Timothy A. Davis, */
|
alpar@1
|
7 |
/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
|
alpar@1
|
8 |
/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
|
alpar@1
|
9 |
/* web: http://www.cise.ufl.edu/research/sparse/amd */
|
alpar@1
|
10 |
/* ------------------------------------------------------------------------- */
|
alpar@1
|
11 |
|
alpar@1
|
12 |
/* Post-ordering of a supernodal elimination tree. */
|
alpar@1
|
13 |
|
alpar@1
|
14 |
#include "amd_internal.h"
|
alpar@1
|
15 |
|
alpar@1
|
16 |
GLOBAL Int AMD_post_tree
|
alpar@1
|
17 |
(
|
alpar@1
|
18 |
Int root, /* root of the tree */
|
alpar@1
|
19 |
Int k, /* start numbering at k */
|
alpar@1
|
20 |
Int Child [ ], /* input argument of size nn, undefined on
|
alpar@1
|
21 |
* output. Child [i] is the head of a link
|
alpar@1
|
22 |
* list of all nodes that are children of node
|
alpar@1
|
23 |
* i in the tree. */
|
alpar@1
|
24 |
const Int Sibling [ ], /* input argument of size nn, not modified.
|
alpar@1
|
25 |
* If f is a node in the link list of the
|
alpar@1
|
26 |
* children of node i, then Sibling [f] is the
|
alpar@1
|
27 |
* next child of node i.
|
alpar@1
|
28 |
*/
|
alpar@1
|
29 |
Int Order [ ], /* output order, of size nn. Order [i] = k
|
alpar@1
|
30 |
* if node i is the kth node of the reordered
|
alpar@1
|
31 |
* tree. */
|
alpar@1
|
32 |
Int Stack [ ] /* workspace of size nn */
|
alpar@1
|
33 |
#ifndef NDEBUG
|
alpar@1
|
34 |
, Int nn /* nodes are in the range 0..nn-1. */
|
alpar@1
|
35 |
#endif
|
alpar@1
|
36 |
)
|
alpar@1
|
37 |
{
|
alpar@1
|
38 |
Int f, head, h, i ;
|
alpar@1
|
39 |
|
alpar@1
|
40 |
#if 0
|
alpar@1
|
41 |
/* --------------------------------------------------------------------- */
|
alpar@1
|
42 |
/* recursive version (Stack [ ] is not used): */
|
alpar@1
|
43 |
/* --------------------------------------------------------------------- */
|
alpar@1
|
44 |
|
alpar@1
|
45 |
/* this is simple, but can caouse stack overflow if nn is large */
|
alpar@1
|
46 |
i = root ;
|
alpar@1
|
47 |
for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
|
alpar@1
|
48 |
{
|
alpar@1
|
49 |
k = AMD_post_tree (f, k, Child, Sibling, Order, Stack, nn) ;
|
alpar@1
|
50 |
}
|
alpar@1
|
51 |
Order [i] = k++ ;
|
alpar@1
|
52 |
return (k) ;
|
alpar@1
|
53 |
#endif
|
alpar@1
|
54 |
|
alpar@1
|
55 |
/* --------------------------------------------------------------------- */
|
alpar@1
|
56 |
/* non-recursive version, using an explicit stack */
|
alpar@1
|
57 |
/* --------------------------------------------------------------------- */
|
alpar@1
|
58 |
|
alpar@1
|
59 |
/* push root on the stack */
|
alpar@1
|
60 |
head = 0 ;
|
alpar@1
|
61 |
Stack [0] = root ;
|
alpar@1
|
62 |
|
alpar@1
|
63 |
while (head >= 0)
|
alpar@1
|
64 |
{
|
alpar@1
|
65 |
/* get head of stack */
|
alpar@1
|
66 |
ASSERT (head < nn) ;
|
alpar@1
|
67 |
i = Stack [head] ;
|
alpar@1
|
68 |
AMD_DEBUG1 (("head of stack "ID" \n", i)) ;
|
alpar@1
|
69 |
ASSERT (i >= 0 && i < nn) ;
|
alpar@1
|
70 |
|
alpar@1
|
71 |
if (Child [i] != EMPTY)
|
alpar@1
|
72 |
{
|
alpar@1
|
73 |
/* the children of i are not yet ordered */
|
alpar@1
|
74 |
/* push each child onto the stack in reverse order */
|
alpar@1
|
75 |
/* so that small ones at the head of the list get popped first */
|
alpar@1
|
76 |
/* and the biggest one at the end of the list gets popped last */
|
alpar@1
|
77 |
for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
|
alpar@1
|
78 |
{
|
alpar@1
|
79 |
head++ ;
|
alpar@1
|
80 |
ASSERT (head < nn) ;
|
alpar@1
|
81 |
ASSERT (f >= 0 && f < nn) ;
|
alpar@1
|
82 |
}
|
alpar@1
|
83 |
h = head ;
|
alpar@1
|
84 |
ASSERT (head < nn) ;
|
alpar@1
|
85 |
for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
|
alpar@1
|
86 |
{
|
alpar@1
|
87 |
ASSERT (h > 0) ;
|
alpar@1
|
88 |
Stack [h--] = f ;
|
alpar@1
|
89 |
AMD_DEBUG1 (("push "ID" on stack\n", f)) ;
|
alpar@1
|
90 |
ASSERT (f >= 0 && f < nn) ;
|
alpar@1
|
91 |
}
|
alpar@1
|
92 |
ASSERT (Stack [h] == i) ;
|
alpar@1
|
93 |
|
alpar@1
|
94 |
/* delete child list so that i gets ordered next time we see it */
|
alpar@1
|
95 |
Child [i] = EMPTY ;
|
alpar@1
|
96 |
}
|
alpar@1
|
97 |
else
|
alpar@1
|
98 |
{
|
alpar@1
|
99 |
/* the children of i (if there were any) are already ordered */
|
alpar@1
|
100 |
/* remove i from the stack and order it. Front i is kth front */
|
alpar@1
|
101 |
head-- ;
|
alpar@1
|
102 |
AMD_DEBUG1 (("pop "ID" order "ID"\n", i, k)) ;
|
alpar@1
|
103 |
Order [i] = k++ ;
|
alpar@1
|
104 |
ASSERT (k <= nn) ;
|
alpar@1
|
105 |
}
|
alpar@1
|
106 |
|
alpar@1
|
107 |
#ifndef NDEBUG
|
alpar@1
|
108 |
AMD_DEBUG1 (("\nStack:")) ;
|
alpar@1
|
109 |
for (h = head ; h >= 0 ; h--)
|
alpar@1
|
110 |
{
|
alpar@1
|
111 |
Int j = Stack [h] ;
|
alpar@1
|
112 |
AMD_DEBUG1 ((" "ID, j)) ;
|
alpar@1
|
113 |
ASSERT (j >= 0 && j < nn) ;
|
alpar@1
|
114 |
}
|
alpar@1
|
115 |
AMD_DEBUG1 (("\n\n")) ;
|
alpar@1
|
116 |
ASSERT (head < nn) ;
|
alpar@1
|
117 |
#endif
|
alpar@1
|
118 |
|
alpar@1
|
119 |
}
|
alpar@1
|
120 |
return (k) ;
|
alpar@1
|
121 |
}
|