src/amd/amd_post_tree.c
changeset 1 c445c931472f
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/amd/amd_post_tree.c	Mon Dec 06 13:09:21 2010 +0100
     1.3 @@ -0,0 +1,121 @@
     1.4 +/* ========================================================================= */
     1.5 +/* === AMD_post_tree ======================================================= */
     1.6 +/* ========================================================================= */
     1.7 +
     1.8 +/* ------------------------------------------------------------------------- */
     1.9 +/* AMD, Copyright (c) Timothy A. Davis,                                      */
    1.10 +/* Patrick R. Amestoy, and Iain S. Duff.  See ../README.txt for License.     */
    1.11 +/* email: davis at cise.ufl.edu    CISE Department, Univ. of Florida.        */
    1.12 +/* web: http://www.cise.ufl.edu/research/sparse/amd                          */
    1.13 +/* ------------------------------------------------------------------------- */
    1.14 +
    1.15 +/* Post-ordering of a supernodal elimination tree.  */
    1.16 +
    1.17 +#include "amd_internal.h"
    1.18 +
    1.19 +GLOBAL Int AMD_post_tree
    1.20 +(
    1.21 +    Int root,                   /* root of the tree */
    1.22 +    Int k,                      /* start numbering at k */
    1.23 +    Int Child [ ],              /* input argument of size nn, undefined on
    1.24 +                                 * output.  Child [i] is the head of a link
    1.25 +                                 * list of all nodes that are children of node
    1.26 +                                 * i in the tree. */
    1.27 +    const Int Sibling [ ],      /* input argument of size nn, not modified.
    1.28 +                                 * If f is a node in the link list of the
    1.29 +                                 * children of node i, then Sibling [f] is the
    1.30 +                                 * next child of node i.
    1.31 +                                 */
    1.32 +    Int Order [ ],              /* output order, of size nn.  Order [i] = k
    1.33 +                                 * if node i is the kth node of the reordered
    1.34 +                                 * tree. */
    1.35 +    Int Stack [ ]               /* workspace of size nn */
    1.36 +#ifndef NDEBUG
    1.37 +    , Int nn                    /* nodes are in the range 0..nn-1. */
    1.38 +#endif
    1.39 +)
    1.40 +{
    1.41 +    Int f, head, h, i ;
    1.42 +
    1.43 +#if 0
    1.44 +    /* --------------------------------------------------------------------- */
    1.45 +    /* recursive version (Stack [ ] is not used): */
    1.46 +    /* --------------------------------------------------------------------- */
    1.47 +
    1.48 +    /* this is simple, but can caouse stack overflow if nn is large */
    1.49 +    i = root ;
    1.50 +    for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
    1.51 +    {
    1.52 +        k = AMD_post_tree (f, k, Child, Sibling, Order, Stack, nn) ;
    1.53 +    }
    1.54 +    Order [i] = k++ ;
    1.55 +    return (k) ;
    1.56 +#endif
    1.57 +
    1.58 +    /* --------------------------------------------------------------------- */
    1.59 +    /* non-recursive version, using an explicit stack */
    1.60 +    /* --------------------------------------------------------------------- */
    1.61 +
    1.62 +    /* push root on the stack */
    1.63 +    head = 0 ;
    1.64 +    Stack [0] = root ;
    1.65 +
    1.66 +    while (head >= 0)
    1.67 +    {
    1.68 +        /* get head of stack */
    1.69 +        ASSERT (head < nn) ;
    1.70 +        i = Stack [head] ;
    1.71 +        AMD_DEBUG1 (("head of stack "ID" \n", i)) ;
    1.72 +        ASSERT (i >= 0 && i < nn) ;
    1.73 +
    1.74 +        if (Child [i] != EMPTY)
    1.75 +        {
    1.76 +            /* the children of i are not yet ordered */
    1.77 +            /* push each child onto the stack in reverse order */
    1.78 +            /* so that small ones at the head of the list get popped first */
    1.79 +            /* and the biggest one at the end of the list gets popped last */
    1.80 +            for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
    1.81 +            {
    1.82 +                head++ ;
    1.83 +                ASSERT (head < nn) ;
    1.84 +                ASSERT (f >= 0 && f < nn) ;
    1.85 +            }
    1.86 +            h = head ;
    1.87 +            ASSERT (head < nn) ;
    1.88 +            for (f = Child [i] ; f != EMPTY ; f = Sibling [f])
    1.89 +            {
    1.90 +                ASSERT (h > 0) ;
    1.91 +                Stack [h--] = f ;
    1.92 +                AMD_DEBUG1 (("push "ID" on stack\n", f)) ;
    1.93 +                ASSERT (f >= 0 && f < nn) ;
    1.94 +            }
    1.95 +            ASSERT (Stack [h] == i) ;
    1.96 +
    1.97 +            /* delete child list so that i gets ordered next time we see it */
    1.98 +            Child [i] = EMPTY ;
    1.99 +        }
   1.100 +        else
   1.101 +        {
   1.102 +            /* the children of i (if there were any) are already ordered */
   1.103 +            /* remove i from the stack and order it.  Front i is kth front */
   1.104 +            head-- ;
   1.105 +            AMD_DEBUG1 (("pop "ID" order "ID"\n", i, k)) ;
   1.106 +            Order [i] = k++ ;
   1.107 +            ASSERT (k <= nn) ;
   1.108 +        }
   1.109 +
   1.110 +#ifndef NDEBUG
   1.111 +        AMD_DEBUG1 (("\nStack:")) ;
   1.112 +        for (h = head ; h >= 0 ; h--)
   1.113 +        {
   1.114 +            Int j = Stack [h] ;
   1.115 +            AMD_DEBUG1 ((" "ID, j)) ;
   1.116 +            ASSERT (j >= 0 && j < nn) ;
   1.117 +        }
   1.118 +        AMD_DEBUG1 (("\n\n")) ;
   1.119 +        ASSERT (head < nn) ;
   1.120 +#endif
   1.121 +
   1.122 +    }
   1.123 +    return (k) ;
   1.124 +}