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 }