#include "util.h"
#include "mtrInt.h"
Go to the source code of this file.
Functions | |
static int | mtrShiftHL (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) |
Variables | |
static char rcsid[] | MTR_UNUSED = "$Id: mtrGroup.c,v 1.18 2009/02/20 02:03:47 fabio Exp $" |
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 355 of file mtrGroup.c.
00357 { 00358 MtrNode *parent; 00359 MtrNode *last; 00360 00361 parent = group->parent; 00362 00363 if (parent == NULL) return(NULL); 00364 if (MTR_TEST(group,MTR_TERMINAL) || group->child == NULL) return(NULL); 00365 00366 /* Make all children of group children of its parent, and make 00367 ** last point to the last child of group. */ 00368 for (last = group->child; last->younger != NULL; last = last->younger) { 00369 last->parent = parent; 00370 } 00371 last->parent = parent; 00372 00373 last->younger = group->younger; 00374 if (group->younger != NULL) { 00375 group->younger->elder = last; 00376 } 00377 00378 group->child->elder = group->elder; 00379 if (group == parent->child) { 00380 parent->child = group->child; 00381 } else { 00382 group->elder->younger = group->child; 00383 } 00384 00385 Mtr_DeallocNode(group); 00386 return(parent); 00387 00388 } /* 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 407 of file mtrGroup.c.
00411 { 00412 MtrNode *node; 00413 00414 #ifdef MTR_DEBUG 00415 /* We cannot have a non-empty proper subgroup of a singleton set. */ 00416 assert(!MTR_TEST(root,MTR_TERMINAL)); 00417 #endif 00418 00419 /* Sanity check. */ 00420 if (size < 1) return(NULL); 00421 00422 /* Check whether current group includes the group sought. This 00423 ** check is necessary at the top-level call. In the subsequent 00424 ** calls it is redundant. */ 00425 if (low < (unsigned int) root->low || 00426 low + size > (unsigned int) (root->low + root->size)) 00427 return(NULL); 00428 00429 if (root->size == size && root->low == low) 00430 return(root); 00431 00432 if (root->child == NULL) 00433 return(NULL); 00434 00435 /* Find all chidren of root that are included in the new group. If 00436 ** the group of any child entirely contains the new group, call 00437 ** Mtr_MakeGroup recursively. */ 00438 node = root->child; 00439 while (low >= (unsigned int) (node->low + node->size)) { 00440 node = node->younger; 00441 } 00442 if (low + size <= (unsigned int) (node->low + node->size)) { 00443 /* The group is contained in the group of node. */ 00444 node = Mtr_FindGroup(node, low, size); 00445 return(node); 00446 } else { 00447 return(NULL); 00448 } 00449 00450 } /* 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 119 of file mtrGroup.c.
00122 { 00123 MtrNode *root; 00124 00125 root = Mtr_InitTree(); 00126 if (root == NULL) return(NULL); 00127 root->flags = MTR_DEFAULT; 00128 root->low = lower; 00129 root->size = size; 00130 return(root); 00131 00132 } /* 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 156 of file mtrGroup.c.
00161 { 00162 MtrNode *node, 00163 *first, 00164 *last, 00165 *previous, 00166 *newn; 00167 00168 /* Sanity check. */ 00169 if (size == 0) 00170 return(NULL); 00171 00172 /* Check whether current group includes new group. This check is 00173 ** necessary at the top-level call. In the subsequent calls it is 00174 ** redundant. */ 00175 if (low < (unsigned int) root->low || 00176 low + size > (unsigned int) (root->low + root->size)) 00177 return(NULL); 00178 00179 /* Trying to create an existing group has the effect of updating 00180 ** the flags. */ 00181 if (root->size == size && root->low == low) { 00182 root->flags = flags; 00183 return(root); 00184 } 00185 00186 /* At this point we know that the new group is properly contained 00187 ** in the group of root. We have two possible cases here: - root 00188 ** is a terminal node; - root has children. */ 00189 00190 /* Root has no children: create a new group. */ 00191 if (root->child == NULL) { 00192 newn = Mtr_AllocNode(); 00193 if (newn == NULL) return(NULL); /* out of memory */ 00194 newn->low = low; 00195 newn->size = size; 00196 newn->flags = flags; 00197 newn->parent = root; 00198 newn->elder = newn->younger = newn->child = NULL; 00199 root->child = newn; 00200 return(newn); 00201 } 00202 00203 /* Root has children: Find all chidren of root that are included 00204 ** in the new group. If the group of any child entirely contains 00205 ** the new group, call Mtr_MakeGroup recursively. */ 00206 previous = NULL; 00207 first = root->child; /* guaranteed to be non-NULL */ 00208 while (first != NULL && low >= (unsigned int) (first->low + first->size)) { 00209 previous = first; 00210 first = first->younger; 00211 } 00212 if (first == NULL) { 00213 /* We have scanned the entire list and we need to append a new 00214 ** child at the end of it. Previous points to the last child 00215 ** of root. */ 00216 newn = Mtr_AllocNode(); 00217 if (newn == NULL) return(NULL); /* out of memory */ 00218 newn->low = low; 00219 newn->size = size; 00220 newn->flags = flags; 00221 newn->parent = root; 00222 newn->elder = previous; 00223 previous->younger = newn; 00224 newn->younger = newn->child = NULL; 00225 return(newn); 00226 } 00227 /* Here first is non-NULL and low < first->low + first->size. */ 00228 if (low >= (unsigned int) first->low && 00229 low + size <= (unsigned int) (first->low + first->size)) { 00230 /* The new group is contained in the group of first. */ 00231 newn = Mtr_MakeGroup(first, low, size, flags); 00232 return(newn); 00233 } else if (low + size <= first->low) { 00234 /* The new group is entirely contained in the gap between 00235 ** previous and first. */ 00236 newn = Mtr_AllocNode(); 00237 if (newn == NULL) return(NULL); /* out of memory */ 00238 newn->low = low; 00239 newn->size = size; 00240 newn->flags = flags; 00241 newn->child = NULL; 00242 newn->parent = root; 00243 newn->elder = previous; 00244 newn->younger = first; 00245 first->elder = newn; 00246 if (previous != NULL) { 00247 previous->younger = newn; 00248 } else { 00249 root->child = newn; 00250 } 00251 return(newn); 00252 } else if (low < (unsigned int) first->low && 00253 low + size < (unsigned int) (first->low + first->size)) { 00254 /* Trying to cut an existing group: not allowed. */ 00255 return(NULL); 00256 } else if (low > first->low) { 00257 /* The new group neither is contained in the group of first 00258 ** (this was tested above) nor contains it. It is therefore 00259 ** trying to cut an existing group: not allowed. */ 00260 return(NULL); 00261 } 00262 00263 /* First holds the pointer to the first child contained in the new 00264 ** group. Here low <= first->low and low + size >= first->low + 00265 ** first->size. One of the two inequalities is strict. */ 00266 last = first->younger; 00267 while (last != NULL && 00268 (unsigned int) (last->low + last->size) < low + size) { 00269 last = last->younger; 00270 } 00271 if (last == NULL) { 00272 /* All the chilren of root from first onward become children 00273 ** of the new group. */ 00274 newn = Mtr_AllocNode(); 00275 if (newn == NULL) return(NULL); /* out of memory */ 00276 newn->low = low; 00277 newn->size = size; 00278 newn->flags = flags; 00279 newn->child = first; 00280 newn->parent = root; 00281 newn->elder = previous; 00282 newn->younger = NULL; 00283 first->elder = NULL; 00284 if (previous != NULL) { 00285 previous->younger = newn; 00286 } else { 00287 root->child = newn; 00288 } 00289 last = first; 00290 while (last != NULL) { 00291 last->parent = newn; 00292 last = last->younger; 00293 } 00294 return(newn); 00295 } 00296 00297 /* Here last != NULL and low + size <= last->low + last->size. */ 00298 if (low + size - 1 >= (unsigned int) last->low && 00299 low + size < (unsigned int) (last->low + last->size)) { 00300 /* Trying to cut an existing group: not allowed. */ 00301 return(NULL); 00302 } 00303 00304 /* First and last point to the first and last of the children of 00305 ** root that are included in the new group. Allocate a new node 00306 ** and make all children of root between first and last chidren of 00307 ** the new node. Previous points to the child of root immediately 00308 ** preceeding first. If it is NULL, then first is the first child 00309 ** of root. */ 00310 newn = Mtr_AllocNode(); 00311 if (newn == NULL) return(NULL); /* out of memory */ 00312 newn->low = low; 00313 newn->size = size; 00314 newn->flags = flags; 00315 newn->child = first; 00316 newn->parent = root; 00317 if (previous == NULL) { 00318 root->child = newn; 00319 } else { 00320 previous->younger = newn; 00321 } 00322 newn->elder = previous; 00323 newn->younger = last->younger; 00324 if (last->younger != NULL) { 00325 last->younger->elder = newn; 00326 } 00327 last->younger = NULL; 00328 first->elder = NULL; 00329 for (node = first; node != NULL; node = node->younger) { 00330 node->parent = newn; 00331 } 00332 00333 return(newn); 00334 00335 } /* 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 535 of file mtrGroup.c.
00538 { 00539 MtrNode *node; 00540 00541 assert(root != NULL); 00542 assert(root->younger == NULL || root->younger->elder == root); 00543 assert(root->elder == NULL || root->elder->younger == root); 00544 #if SIZEOF_VOID_P == 8 00545 if (!silent) (void) printf("(%u",root->low); 00546 #else 00547 if (!silent) (void) printf("(%hu",root->low); 00548 #endif 00549 if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) { 00550 if (!silent) (void) printf(","); 00551 } else { 00552 node = root->child; 00553 while (node != NULL) { 00554 assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size)); 00555 assert(node->parent == root); 00556 Mtr_PrintGroups(node,silent); 00557 node = node->younger; 00558 } 00559 } 00560 if (!silent) { 00561 #if SIZEOF_VOID_P == 8 00562 (void) printf("%u", root->low + root->size - 1); 00563 #else 00564 (void) printf("%hu", root->low + root->size - 1); 00565 #endif 00566 if (root->flags != MTR_DEFAULT) { 00567 (void) printf("|"); 00568 if (MTR_TEST(root,MTR_FIXED)) (void) printf("F"); 00569 if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N"); 00570 if (MTR_TEST(root,MTR_SOFT)) (void) printf("S"); 00571 } 00572 (void) printf(")"); 00573 if (root->parent == NULL) (void) printf("\n"); 00574 } 00575 assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0); 00576 return; 00577 00578 } /* 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 609 of file mtrGroup.c.
00612 { 00613 int low; 00614 int size; 00615 int err; 00616 unsigned int flags; 00617 MtrNode *root; 00618 MtrNode *node; 00619 char attrib[8*sizeof(unsigned int)+1]; 00620 char *c; 00621 00622 root = Mtr_InitGroupTree(0,nleaves); 00623 if (root == NULL) return NULL; 00624 00625 while (! feof(fp)) { 00626 /* Read a triple and check for consistency. */ 00627 err = fscanf(fp, "%d %d %s", &low, &size, attrib); 00628 if (err == EOF) { 00629 break; 00630 } else if (err != 3) { 00631 Mtr_FreeTree(root); 00632 return(NULL); 00633 } else if (low < 0 || low+size > nleaves || size < 1) { 00634 Mtr_FreeTree(root); 00635 return(NULL); 00636 } else if (strlen(attrib) > 8 * sizeof(MtrHalfWord)) { 00637 /* Not enough bits in the flags word to store these many 00638 ** attributes. */ 00639 Mtr_FreeTree(root); 00640 return(NULL); 00641 } 00642 00643 /* Parse the flag string. Currently all flags are permitted, 00644 ** to make debugging easier. Normally, specifying NEWNODE 00645 ** wouldn't be allowed. */ 00646 flags = MTR_DEFAULT; 00647 for (c=attrib; *c != 0; c++) { 00648 switch (*c) { 00649 case 'D': 00650 break; 00651 case 'F': 00652 flags |= MTR_FIXED; 00653 break; 00654 case 'N': 00655 flags |= MTR_NEWNODE; 00656 break; 00657 case 'S': 00658 flags |= MTR_SOFT; 00659 break; 00660 case 'T': 00661 flags |= MTR_TERMINAL; 00662 break; 00663 default: 00664 return NULL; 00665 } 00666 } 00667 node = Mtr_MakeGroup(root, (MtrHalfWord) low, (MtrHalfWord) size, 00668 flags); 00669 if (node == NULL) { 00670 Mtr_FreeTree(root); 00671 return(NULL); 00672 } 00673 } 00674 00675 return(root); 00676 00677 } /* 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 468 of file mtrGroup.c.
00471 { 00472 MtrNode *node; 00473 MtrNode *parent; 00474 int sizeFirst; 00475 int sizeSecond; 00476 00477 if (second->younger == first) { /* make first first */ 00478 node = first; 00479 first = second; 00480 second = node; 00481 } else if (first->younger != second) { /* non-adjacent */ 00482 return(0); 00483 } 00484 00485 sizeFirst = first->size; 00486 sizeSecond = second->size; 00487 00488 /* Swap the two nodes. */ 00489 parent = first->parent; 00490 if (parent == NULL || second->parent != parent) return(0); 00491 if (parent->child == first) { 00492 parent->child = second; 00493 } else { /* first->elder != NULL */ 00494 first->elder->younger = second; 00495 } 00496 if (second->younger != NULL) { 00497 second->younger->elder = first; 00498 } 00499 first->younger = second->younger; 00500 second->elder = first->elder; 00501 first->elder = second; 00502 second->younger = first; 00503 00504 /* Adjust the high and low fields. */ 00505 if (!mtrShiftHL(first,sizeSecond)) return(0); 00506 if (!mtrShiftHL(second,-sizeFirst)) return(0); 00507 00508 return(1); 00509 00510 } /* end of Mtr_SwapGroups */
static int mtrShiftHL | ( | MtrNode * | node, | |
int | shift | |||
) | [static] |
AutomaticStart
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 704 of file mtrGroup.c.
00707 { 00708 MtrNode *auxnode; 00709 int low; 00710 00711 low = (int) node->low; 00712 00713 00714 low += shift; 00715 00716 if (low < 0 || low + (int) (node->size - 1) > (int) MTR_MAXHIGH) return(0); 00717 00718 node->low = (MtrHalfWord) low; 00719 00720 if (!MTR_TEST(node,MTR_TERMINAL) && node->child != NULL) { 00721 auxnode = node->child; 00722 do { 00723 if (!mtrShiftHL(auxnode,shift)) return(0); 00724 auxnode = auxnode->younger; 00725 } while (auxnode != NULL); 00726 } 00727 00728 return(1); 00729 00730 } /* end of mtrShiftHL */
char rcsid [] MTR_UNUSED = "$Id: mtrGroup.c,v 1.18 2009/02/20 02:03:47 fabio 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 [Copyright (c) 1995-2004, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]
Definition at line 83 of file mtrGroup.c.