src/mtr/mtrGroup.c File Reference

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

Go to the source code of this file.

Functions

static int mtrShiftHL (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)

Variables

static char rcsid[] MTR_UNUSED = "$Id: mtrGroup.c,v 1.18 2009/02/20 02:03:47 fabio Exp $"

Function Documentation

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 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 */

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 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 */

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 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.

  • 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 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):

  • 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 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 */

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 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 */


Variable Documentation

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:

  • mtrShiftHL

]

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.


Generated on Tue Jan 12 13:57:28 2010 for glu-2.2 by  doxygen 1.6.1