#include "util_hack.h"
#include "mtrInt.h"
Go to the source code of this file.
Functions | |
static int mtrShiftHL | ARGS ((MtrNode *node, int shift)) |
MtrNode * | Mtr_InitGroupTree (int lower, int size) |
MtrNode * | Mtr_MakeGroup (MtrNode *root, unsigned int low, unsigned int size, unsigned int flags) |
MtrNode * | Mtr_DissolveGroup (MtrNode *group) |
MtrNode * | Mtr_FindGroup (MtrNode *root, unsigned int low, unsigned int size) |
int | Mtr_SwapGroups (MtrNode *first, MtrNode *second) |
void | Mtr_PrintGroups (MtrNode *root, int silent) |
MtrNode * | Mtr_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 $" |
static int mtrShiftHL ARGS | ( | (MtrNode *node, int shift) | ) | [static] |
AutomaticStart
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 */
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 */
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.
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):
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 */
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 */
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:
]
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.