src/bdd/mtr/mtrGroup.c File Reference

#include "util_hack.h"
#include "mtrInt.h"
Include dependency graph for mtrGroup.c:

Go to the source code of this file.

Functions

static int mtrShiftHL ARGS ((MtrNode *node, int shift))
MtrNodeMtr_InitGroupTree (int lower, int size)
MtrNodeMtr_MakeGroup (MtrNode *root, unsigned int low, unsigned int size, unsigned int flags)
MtrNodeMtr_DissolveGroup (MtrNode *group)
MtrNodeMtr_FindGroup (MtrNode *root, unsigned int low, unsigned int size)
int Mtr_SwapGroups (MtrNode *first, MtrNode *second)
void Mtr_PrintGroups (MtrNode *root, int silent)
MtrNodeMtr_ReadGroups (FILE *fp, int nleaves)
static int mtrShiftHL (MtrNode *node, int shift)

Variables

static char rcsid[] MTR_UNUSED = "$Id: mtrGroup.c,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $"

Function Documentation

static int mtrShiftHL ARGS ( (MtrNode *node, int shift)   )  [static]

AutomaticStart

MtrNode* Mtr_DissolveGroup ( MtrNode group  ) 

Function********************************************************************

Synopsis [Merges the children of `group' with the children of its parent.]

Description [Merges the children of `group' with the children of its parent. Disposes of the node pointed by group. If group is the root of the group tree, this procedure leaves the tree unchanged. Returns the pointer to the parent of `group' upon successful termination; NULL otherwise.]

SideEffects [None]

SeeAlso [Mtr_MakeGroup]

Definition at line 328 of file mtrGroup.c.

00330 {
00331     MtrNode *parent;
00332     MtrNode *last;
00333 
00334     parent = group->parent;
00335 
00336     if (parent == NULL) return(NULL);
00337     if (MTR_TEST(group,MTR_TERMINAL) || group->child == NULL) return(NULL);
00338 
00339     /* Make all children of group children of its parent, and make
00340     ** last point to the last child of group. */
00341     for (last = group->child; last->younger != NULL; last = last->younger) {
00342         last->parent = parent;
00343     }
00344     last->parent = parent;
00345 
00346     last->younger = group->younger;
00347     if (group->younger != NULL) {
00348         group->younger->elder = last;
00349     }
00350 
00351     group->child->elder = group->elder;
00352     if (group == parent->child) {
00353         parent->child = group->child;
00354     } else {
00355         group->elder->younger = group->child;
00356     }
00357 
00358     Mtr_DeallocNode(group);
00359     return(parent);
00360 
00361 } /* end of Mtr_DissolveGroup */

MtrNode* Mtr_FindGroup ( MtrNode root,
unsigned int  low,
unsigned int  size 
)

Function********************************************************************

Synopsis [Finds a group with size leaves starting at low, if it exists.]

Description [Finds a group with size leaves starting at low, if it exists. This procedure relies on the low and size fields of each node. It also assumes that the children of each node are sorted in order of increasing low. Returns the pointer to the root of the group upon successful termination; NULL otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 380 of file mtrGroup.c.

00384 {
00385     MtrNode *node;
00386 
00387 #ifdef MTR_DEBUG
00388     /* We cannot have a non-empty proper subgroup of a singleton set. */
00389     assert(!MTR_TEST(root,MTR_TERMINAL));
00390 #endif
00391 
00392     /* Sanity check. */
00393     if (size < 1) return(NULL);
00394 
00395     /* Check whether current group includes the group sought.  This
00396     ** check is necessary at the top-level call.  In the subsequent
00397     ** calls it is redundant. */
00398     if (low < (unsigned int) root->low ||
00399         low + size > (unsigned int) (root->low + root->size))
00400         return(NULL);
00401 
00402     if (root->size == size && root->low == low)
00403         return(root);
00404 
00405     if (root->child == NULL)
00406         return(NULL);
00407 
00408     /* Find all chidren of root that are included in the new group. If
00409     ** the group of any child entirely contains the new group, call
00410     ** Mtr_MakeGroup recursively.  */
00411     node = root->child;
00412     while (low >= (unsigned int) (node->low + node->size)) {
00413         node = node->younger;
00414     }
00415     if (low + size <= (unsigned int) (node->low + node->size)) {
00416         /* The group is contained in the group of node. */
00417         node = Mtr_FindGroup(node, low, size);
00418         return(node);
00419     } else {
00420         return(NULL);
00421     }
00422 
00423 } /* end of Mtr_FindGroup */

MtrNode* Mtr_InitGroupTree ( int  lower,
int  size 
)

AutomaticEnd Function********************************************************************

Synopsis [Allocate new tree.]

Description [Allocate new tree with one node, whose low and size fields are specified by the lower and size parameters. Returns pointer to tree root.]

SideEffects [None]

SeeAlso [Mtr_InitTree Mtr_FreeTree]

Definition at line 92 of file mtrGroup.c.

00095 {
00096     MtrNode *root;
00097 
00098     root = Mtr_InitTree();
00099     if (root == NULL) return(NULL);
00100     root->flags = MTR_DEFAULT;
00101     root->low = lower;
00102     root->size = size;
00103     return(root);
00104 
00105 } /* end of Mtr_InitGroupTree */

MtrNode* Mtr_MakeGroup ( MtrNode root,
unsigned int  low,
unsigned int  size,
unsigned int  flags 
)

Function********************************************************************

Synopsis [Makes a new group with size leaves starting at low.]

Description [Makes a new group with size leaves starting at low. If the new group intersects an existing group, it must either contain it or be contained by it. This procedure relies on the low and size fields of each node. It also assumes that the children of each node are sorted in order of increasing low. In case of a valid request, the flags of the new group are set to the value passed in `flags.' This can also be used to change the flags of an existing group. Returns the pointer to the root of the new group upon successful termination; NULL otherwise. If the group already exists, the pointer to its root is returned.]

SideEffects [None]

SeeAlso [Mtr_DissolveGroup Mtr_ReadGroups Mtr_FindGroup]

Definition at line 129 of file mtrGroup.c.

00134 {
00135     MtrNode *node,
00136             *first,
00137             *last,
00138             *previous,
00139             *newn;
00140 
00141     /* Sanity check. */
00142     if (size == 0)
00143         return(NULL);
00144 
00145     /* Check whether current group includes new group.  This check is
00146     ** necessary at the top-level call.  In the subsequent calls it is
00147     ** redundant. */
00148     if (low < (unsigned int) root->low ||
00149         low + size > (unsigned int) (root->low + root->size))
00150         return(NULL);
00151 
00152     /* Trying to create an existing group has the effect of updating
00153     ** the flags. */
00154     if (root->size == size && root->low == low) {
00155         root->flags = flags;
00156         return(root);
00157     }
00158 
00159     /* At this point we know that the new group is properly contained
00160     ** in the group of root. We have two possible cases here: - root
00161     ** is a terminal node; - root has children. */
00162 
00163     /* Root has no children: create a new group. */
00164     if (root->child == NULL) {
00165         newn = Mtr_AllocNode();
00166         if (newn == NULL) return(NULL); /* out of memory */
00167         newn->low = low;
00168         newn->size = size;
00169         newn->flags = flags;
00170         newn->parent = root;
00171         newn->elder = newn->younger = newn->child = NULL;
00172         root->child = newn;
00173         return(newn);
00174     }
00175 
00176     /* Root has children: Find all chidren of root that are included
00177     ** in the new group. If the group of any child entirely contains
00178     ** the new group, call Mtr_MakeGroup recursively. */
00179     previous = NULL;
00180     first = root->child; /* guaranteed to be non-NULL */
00181     while (first != NULL && low >= (unsigned int) (first->low + first->size)) {
00182         previous = first;
00183         first = first->younger;
00184     }
00185     if (first == NULL) {
00186         /* We have scanned the entire list and we need to append a new
00187         ** child at the end of it.  Previous points to the last child
00188         ** of root. */
00189         newn = Mtr_AllocNode();
00190         if (newn == NULL) return(NULL); /* out of memory */
00191         newn->low = low;
00192         newn->size = size;
00193         newn->flags = flags;
00194         newn->parent = root;
00195         newn->elder = previous;
00196         previous->younger = newn;
00197         newn->younger = newn->child = NULL;
00198         return(newn);
00199     }
00200     /* Here first is non-NULL and low < first->low + first->size. */
00201     if (low >= (unsigned int) first->low &&
00202         low + size <= (unsigned int) (first->low + first->size)) {
00203         /* The new group is contained in the group of first. */
00204         newn = Mtr_MakeGroup(first, low, size, flags);
00205         return(newn);
00206     } else if (low + size <= first->low) {
00207         /* The new group is entirely contained in the gap between
00208         ** previous and first. */
00209         newn = Mtr_AllocNode();
00210         if (newn == NULL) return(NULL); /* out of memory */
00211         newn->low = low;
00212         newn->size = size;
00213         newn->flags = flags;
00214         newn->child = NULL;
00215         newn->parent = root;
00216         newn->elder = previous;
00217         newn->younger = first;
00218         first->elder = newn;
00219         if (previous != NULL) {
00220             previous->younger = newn;
00221         } else {
00222             root->child = newn;
00223         }
00224         return(newn);
00225     } else if (low < (unsigned int) first->low &&
00226                low + size < (unsigned int) (first->low + first->size)) {
00227         /* Trying to cut an existing group: not allowed. */
00228         return(NULL);
00229     } else if (low > first->low) {
00230         /* The new group neither is contained in the group of first
00231         ** (this was tested above) nor contains it. It is therefore
00232         ** trying to cut an existing group: not allowed. */
00233         return(NULL);
00234     }
00235 
00236     /* First holds the pointer to the first child contained in the new
00237     ** group. Here low <= first->low and low + size >= first->low +
00238     ** first->size.  One of the two inequalities is strict. */
00239     last = first->younger;
00240     while (last != NULL &&
00241            (unsigned int) (last->low + last->size) < low + size) {
00242         last = last->younger;
00243     }
00244     if (last == NULL) {
00245         /* All the chilren of root from first onward become children
00246         ** of the new group. */
00247         newn = Mtr_AllocNode();
00248         if (newn == NULL) return(NULL); /* out of memory */
00249         newn->low = low;
00250         newn->size = size;
00251         newn->flags = flags;
00252         newn->child = first;
00253         newn->parent = root;
00254         newn->elder = previous;
00255         newn->younger = NULL;
00256         first->elder = NULL;
00257         if (previous != NULL) {
00258             previous->younger = newn;
00259         } else {
00260             root->child = newn;
00261         }
00262         last = first;
00263         while (last != NULL) {
00264             last->parent = newn;
00265             last = last->younger;
00266         }
00267         return(newn);
00268     }
00269 
00270     /* Here last != NULL and low + size <= last->low + last->size. */
00271     if (low + size - 1 >= (unsigned int) last->low &&
00272         low + size < (unsigned int) (last->low + last->size)) {
00273         /* Trying to cut an existing group: not allowed. */
00274         return(NULL);
00275     }
00276 
00277     /* First and last point to the first and last of the children of
00278     ** root that are included in the new group. Allocate a new node
00279     ** and make all children of root between first and last chidren of
00280     ** the new node.  Previous points to the child of root immediately
00281     ** preceeding first. If it is NULL, then first is the first child
00282     ** of root. */
00283     newn = Mtr_AllocNode();
00284     if (newn == NULL) return(NULL);     /* out of memory */
00285     newn->low = low;
00286     newn->size = size;
00287     newn->flags = flags;
00288     newn->child = first;
00289     newn->parent = root;
00290     if (previous == NULL) {
00291         root->child = newn;
00292     } else {
00293         previous->younger = newn;
00294     }
00295     newn->elder = previous;
00296     newn->younger = last->younger;
00297     if (last->younger != NULL) {
00298         last->younger->elder = newn;
00299     }
00300     last->younger = NULL;
00301     first->elder = NULL;
00302     for (node = first; node != NULL; node = node->younger) {
00303         node->parent = newn;
00304     }
00305 
00306     return(newn);
00307 
00308 } /* end of Mtr_MakeGroup */

void Mtr_PrintGroups ( MtrNode root,
int  silent 
)

Function********************************************************************

Synopsis [Prints the groups as a parenthesized list.]

Description [Prints the groups as a parenthesized list. After each group, the group's flag are printed, preceded by a `|'. For each flag (except MTR_TERMINAL) a character is printed.

  • F: MTR_FIXED
  • N: MTR_NEWNODE
  • S: MTR_SOFT

The second argument, silent, if different from 0, causes Mtr_PrintGroups to only check the syntax of the group tree. ]

SideEffects [None]

SeeAlso [Mtr_PrintTree]

Definition at line 508 of file mtrGroup.c.

00511 {
00512     MtrNode *node;
00513 
00514     assert(root != NULL);
00515     assert(root->younger == NULL || root->younger->elder == root);
00516     assert(root->elder == NULL || root->elder->younger == root);
00517     if (!silent) (void) printf("(%d",root->low);
00518     if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) {
00519         if (!silent) (void) printf(",");
00520     } else {
00521         node = root->child;
00522         while (node != NULL) {
00523             assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size));
00524             assert(node->parent == root);
00525             Mtr_PrintGroups(node,silent);
00526             node = node->younger;
00527         }
00528     }
00529     if (!silent) {
00530         (void) printf("%d", root->low + root->size - 1);
00531         if (root->flags != MTR_DEFAULT) {
00532             (void) printf("|");
00533             if (MTR_TEST(root,MTR_FIXED)) (void) printf("F");
00534             if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N");
00535             if (MTR_TEST(root,MTR_SOFT)) (void) printf("S");
00536         }
00537         (void) printf(")");
00538         if (root->parent == NULL) (void) printf("\n");
00539     }
00540     assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0);
00541     return;
00542 
00543 } /* end of Mtr_PrintGroups */

MtrNode* Mtr_ReadGroups ( FILE *  fp,
int  nleaves 
)

Function********************************************************************

Synopsis [Reads groups from a file and creates a group tree.]

Description [Reads groups from a file and creates a group tree. Each group is specified by three fields: <xmp> low size flags. </xmp> Low and size are (short) integers. Flags is a string composed of the following characters (with associated translation):

  • D: MTR_DEFAULT
  • F: MTR_FIXED
  • N: MTR_NEWNODE
  • S: MTR_SOFT
  • T: MTR_TERMINAL

Normally, the only flags that are needed are D and F. Groups and fields are separated by white space (spaces, tabs, and newlines). Returns a pointer to the group tree if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [Mtr_InitGroupTree Mtr_MakeGroup]

Definition at line 574 of file mtrGroup.c.

00577 {
00578     int low;
00579     int size;
00580     int err;
00581     unsigned int flags;
00582     MtrNode *root;
00583     MtrNode *node;
00584     char attrib[8*sizeof(unsigned int)+1];
00585     char *c;
00586 
00587     root = Mtr_InitGroupTree(0,nleaves);
00588     if (root == NULL) return NULL;
00589 
00590     while (! feof(fp)) {
00591         /* Read a triple and check for consistency. */
00592         err = fscanf(fp, "%d %d %s", &low, &size, attrib);
00593         if (err == EOF) {
00594             break;
00595         } else if (err != 3) {
00596             return(NULL);
00597         } else if (low < 0 || low+size > nleaves || size < 1) {
00598             return(NULL);
00599         } else if (strlen(attrib) > 8 * sizeof(MtrHalfWord)) {
00600             /* Not enough bits in the flags word to store these many
00601             ** attributes. */
00602             return(NULL);
00603         }
00604 
00605         /* Parse the flag string. Currently all flags are permitted,
00606         ** to make debugging easier. Normally, specifying NEWNODE
00607         ** wouldn't be allowed. */
00608         flags = MTR_DEFAULT;
00609         for (c=attrib; *c != 0; c++) {
00610             switch (*c) {
00611             case 'D':
00612                 break;
00613             case 'F':
00614                 flags |= MTR_FIXED;
00615                 break;
00616             case 'N':
00617                 flags |= MTR_NEWNODE;
00618                 break;
00619             case 'S':
00620                 flags |= MTR_SOFT;
00621                 break;
00622             case 'T':
00623                 flags |= MTR_TERMINAL;
00624                 break;
00625             default:
00626                 return NULL;
00627             }
00628         }
00629         node = Mtr_MakeGroup(root, (MtrHalfWord) low, (MtrHalfWord) size,
00630                              flags);
00631         if (node == NULL) return(NULL);
00632     }
00633 
00634     return(root);
00635 
00636 } /* end of Mtr_ReadGroups */

int Mtr_SwapGroups ( MtrNode first,
MtrNode second 
)

Function********************************************************************

Synopsis [Swaps two children of a tree node.]

Description [Swaps two children of a tree node. Adjusts the high and low fields of the two nodes and their descendants. The two children must be adjacent. However, first may be the younger sibling of second. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 441 of file mtrGroup.c.

00444 {
00445     MtrNode *node;
00446     MtrNode *parent;
00447     int sizeFirst;
00448     int sizeSecond;
00449 
00450     if (second->younger == first) { /* make first first */
00451         node = first;
00452         first = second;
00453         second = node;
00454     } else if (first->younger != second) { /* non-adjacent */
00455         return(0);
00456     }
00457 
00458     sizeFirst = first->size;
00459     sizeSecond = second->size;
00460 
00461     /* Swap the two nodes. */
00462     parent = first->parent;
00463     if (parent == NULL || second->parent != parent) return(0);
00464     if (parent->child == first) {
00465         parent->child = second;
00466     } else { /* first->elder != NULL */
00467         first->elder->younger = second;
00468     }
00469     if (second->younger != NULL) {
00470         second->younger->elder = first;
00471     }
00472     first->younger = second->younger;
00473     second->elder = first->elder;
00474     first->elder = second;
00475     second->younger = first;
00476 
00477     /* Adjust the high and low fields. */
00478     if (!mtrShiftHL(first,sizeSecond)) return(0);
00479     if (!mtrShiftHL(second,-sizeFirst)) return(0);
00480 
00481     return(1);
00482 
00483 } /* end of Mtr_SwapGroups */

static int mtrShiftHL ( MtrNode node,
int  shift 
) [static]

Function********************************************************************

Synopsis [Adjusts the low fields of a node and its descendants.]

Description [Adjusts the low fields of a node and its descendants. Adds shift to low of each node. Checks that no out-of-bounds values result. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 663 of file mtrGroup.c.

00666 {
00667     MtrNode *auxnode;
00668     int low;
00669 
00670     low = (int) node->low;
00671 
00672 
00673     low += shift;
00674 
00675     if (low < 0 || low + (int) (node->size - 1) > (int) MTR_MAXHIGH) return(0);
00676 
00677     node->low = (MtrHalfWord) low;
00678 
00679     if (!MTR_TEST(node,MTR_TERMINAL) && node->child != NULL) {
00680         auxnode = node->child;
00681         do {
00682             if (!mtrShiftHL(auxnode,shift)) return(0);
00683             auxnode = auxnode->younger;
00684         } while (auxnode != NULL);
00685     }
00686 
00687     return(1);
00688 
00689 } /* end of mtrShiftHL */


Variable Documentation

char rcsid [] MTR_UNUSED = "$Id: mtrGroup.c,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $" [static]

CFile***********************************************************************

FileName [mtrGroup.c]

PackageName [mtr]

Synopsis [Functions to support group specification for reordering.]

Description [External procedures included in this module:

Static procedures included in this module:

  • mtrShiftHL

]

SeeAlso [cudd package]

Author [Fabio Somenzi]

Copyright [This file was created at the University of Colorado at Boulder. The University of Colorado at Boulder makes no warranty about the suitability of this software for any purpose. It is presented on an AS IS basis.]

Definition at line 56 of file mtrGroup.c.


Generated on Tue Jan 5 12:19:00 2010 for abc70930 by  doxygen 1.6.1