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