You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
398 lines
9.3 KiB
398 lines
9.3 KiB
/**
|
|
@file
|
|
|
|
@ingroup mtr
|
|
|
|
@brief Basic manipulation of multiway branching trees.
|
|
|
|
@see cudd package
|
|
|
|
@author Fabio Somenzi
|
|
|
|
@copyright@parblock
|
|
Copyright (c) 1995-2015, 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.
|
|
@endparblock
|
|
|
|
*/
|
|
|
|
#include "util.h"
|
|
#include "mtrInt.h"
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Constant declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Stucture declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Type declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Variable declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Macro declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/** \cond */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Static function prototypes */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/** \endcond */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of exported functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
@brief Allocates new tree node.
|
|
|
|
@return pointer to node.
|
|
|
|
@sideeffect None
|
|
|
|
@see Mtr_DeallocNode
|
|
|
|
*/
|
|
MtrNode *
|
|
Mtr_AllocNode(void)
|
|
{
|
|
MtrNode *node;
|
|
|
|
node = ALLOC(MtrNode,1);
|
|
node->flags = node->low = node->size = node->index = 0;
|
|
return node;
|
|
|
|
} /* Mtr_AllocNode */
|
|
|
|
|
|
/**
|
|
@brief Deallocates tree node.
|
|
|
|
@sideeffect None
|
|
|
|
@see Mtr_AllocNode
|
|
|
|
*/
|
|
void
|
|
Mtr_DeallocNode(
|
|
MtrNode * node /**< node to be deallocated */)
|
|
{
|
|
FREE(node);
|
|
return;
|
|
|
|
} /* end of Mtr_DeallocNode */
|
|
|
|
|
|
/**
|
|
@brief Initializes tree with one node.
|
|
|
|
@return pointer to node.
|
|
|
|
@sideeffect None
|
|
|
|
@see Mtr_FreeTree Mtr_InitGroupTree
|
|
|
|
*/
|
|
MtrNode *
|
|
Mtr_InitTree(void)
|
|
{
|
|
MtrNode *node;
|
|
|
|
node = Mtr_AllocNode();
|
|
if (node == NULL) return(NULL);
|
|
|
|
node->parent = node->child = node->elder = node->younger = NULL;
|
|
|
|
return(node);
|
|
|
|
} /* end of Mtr_InitTree */
|
|
|
|
|
|
/**
|
|
@brief Disposes of tree rooted at node.
|
|
|
|
@sideeffect None
|
|
|
|
@see Mtr_InitTree
|
|
|
|
*/
|
|
void
|
|
Mtr_FreeTree(
|
|
MtrNode * node)
|
|
{
|
|
if (node == NULL) return;
|
|
if (! MTR_TEST(node,MTR_TERMINAL)) Mtr_FreeTree(node->child);
|
|
Mtr_FreeTree(node->younger);
|
|
Mtr_DeallocNode(node);
|
|
return;
|
|
|
|
} /* end of Mtr_FreeTree */
|
|
|
|
|
|
/**
|
|
@brief Makes a copy of tree.
|
|
|
|
@details If parameter expansion is greater than 1, it will expand
|
|
the tree by that factor. It is an error for expansion to be less
|
|
than 1.
|
|
|
|
@return a pointer to the copy if successful; NULL otherwise.
|
|
|
|
@sideeffect None
|
|
|
|
@see Mtr_InitTree
|
|
|
|
*/
|
|
MtrNode *
|
|
Mtr_CopyTree(
|
|
MtrNode const * node,
|
|
int expansion)
|
|
{
|
|
MtrNode *copy;
|
|
|
|
if (node == NULL) return(NULL);
|
|
if (expansion < 1) return(NULL);
|
|
copy = Mtr_AllocNode();
|
|
if (copy == NULL) return(NULL);
|
|
copy->parent = copy->elder = copy->child = copy->younger = NULL;
|
|
if (node->child != NULL) {
|
|
copy->child = Mtr_CopyTree(node->child, expansion);
|
|
if (copy->child == NULL) {
|
|
Mtr_DeallocNode(copy);
|
|
return(NULL);
|
|
}
|
|
}
|
|
if (node->younger != NULL) {
|
|
copy->younger = Mtr_CopyTree(node->younger, expansion);
|
|
if (copy->younger == NULL) {
|
|
Mtr_FreeTree(copy);
|
|
return(NULL);
|
|
}
|
|
}
|
|
copy->flags = node->flags;
|
|
copy->low = node->low * expansion;
|
|
copy->size = node->size * expansion;
|
|
copy->index = node->index * expansion;
|
|
if (copy->younger) copy->younger->elder = copy;
|
|
if (copy->child) {
|
|
MtrNode *auxnode = copy->child;
|
|
while (auxnode != NULL) {
|
|
auxnode->parent = copy;
|
|
auxnode = auxnode->younger;
|
|
}
|
|
}
|
|
return(copy);
|
|
|
|
} /* end of Mtr_CopyTree */
|
|
|
|
|
|
/**
|
|
@brief Makes child the first child of parent.
|
|
|
|
@sideeffect None
|
|
|
|
@see Mtr_MakeLastChild Mtr_CreateFirstChild
|
|
|
|
*/
|
|
void
|
|
Mtr_MakeFirstChild(
|
|
MtrNode * parent,
|
|
MtrNode * child)
|
|
{
|
|
child->parent = parent;
|
|
child->younger = parent->child;
|
|
child->elder = NULL;
|
|
if (parent->child != NULL) {
|
|
#ifdef MTR_DEBUG
|
|
assert(parent->child->elder == NULL);
|
|
#endif
|
|
parent->child->elder = child;
|
|
}
|
|
parent->child = child;
|
|
return;
|
|
|
|
} /* end of Mtr_MakeFirstChild */
|
|
|
|
|
|
/**
|
|
@brief Makes child the last child of parent.
|
|
|
|
@sideeffect None
|
|
|
|
@see Mtr_MakeFirstChild Mtr_CreateLastChild
|
|
|
|
*/
|
|
void
|
|
Mtr_MakeLastChild(
|
|
MtrNode * parent,
|
|
MtrNode * child)
|
|
{
|
|
MtrNode *node;
|
|
|
|
child->younger = NULL;
|
|
|
|
if (parent->child == NULL) {
|
|
parent->child = child;
|
|
child->elder = NULL;
|
|
} else {
|
|
for (node = parent->child;
|
|
node->younger != NULL;
|
|
node = node->younger);
|
|
node->younger = child;
|
|
child->elder = node;
|
|
}
|
|
child->parent = parent;
|
|
return;
|
|
|
|
} /* end of Mtr_MakeLastChild */
|
|
|
|
|
|
/**
|
|
@brief Creates a new node and makes it the first child of parent.
|
|
|
|
@return pointer to new child.
|
|
|
|
@sideeffect None
|
|
|
|
@see Mtr_MakeFirstChild Mtr_CreateLastChild
|
|
|
|
*/
|
|
MtrNode *
|
|
Mtr_CreateFirstChild(
|
|
MtrNode * parent)
|
|
{
|
|
MtrNode *child;
|
|
|
|
child = Mtr_AllocNode();
|
|
if (child == NULL) return(NULL);
|
|
|
|
child->child = NULL;
|
|
Mtr_MakeFirstChild(parent,child);
|
|
return(child);
|
|
|
|
} /* end of Mtr_CreateFirstChild */
|
|
|
|
|
|
/**
|
|
@brief Creates a new node and makes it the last child of parent.
|
|
|
|
@return pointer to new child.
|
|
|
|
@sideeffect None
|
|
|
|
@see Mtr_MakeLastChild Mtr_CreateFirstChild
|
|
|
|
*/
|
|
MtrNode *
|
|
Mtr_CreateLastChild(
|
|
MtrNode * parent)
|
|
{
|
|
MtrNode *child;
|
|
|
|
child = Mtr_AllocNode();
|
|
if (child == NULL) return(NULL);
|
|
|
|
child->child = NULL;
|
|
Mtr_MakeLastChild(parent,child);
|
|
return(child);
|
|
|
|
} /* end of Mtr_CreateLastChild */
|
|
|
|
|
|
/**
|
|
@brief Makes second the next sibling of first.
|
|
|
|
@details Second becomes a child of the parent of first.
|
|
|
|
@sideeffect None
|
|
|
|
*/
|
|
void
|
|
Mtr_MakeNextSibling(
|
|
MtrNode * first,
|
|
MtrNode * second)
|
|
{
|
|
second->parent = first->parent;
|
|
second->elder = first;
|
|
second->younger = first->younger;
|
|
if (first->younger != NULL) {
|
|
first->younger->elder = second;
|
|
}
|
|
first->younger = second;
|
|
return;
|
|
|
|
} /* end of Mtr_MakeNextSibling */
|
|
|
|
|
|
/**
|
|
@brief Prints a tree, one node per line.
|
|
|
|
@sideeffect None
|
|
|
|
@see Mtr_PrintGroups
|
|
|
|
*/
|
|
void
|
|
Mtr_PrintTree(
|
|
MtrNode const * node)
|
|
{
|
|
if (node == NULL) return;
|
|
(void) fprintf(stdout,
|
|
"N=0x%-8" PRIxPTR " C=0x%-8" PRIxPTR " Y=0x%-8" PRIxPTR
|
|
" E=0x%-8" PRIxPTR " P=0x%-8" PRIxPTR " F=%x L=%u S=%u\n",
|
|
(uintptr_t) node, (uintptr_t) node->child,
|
|
(uintptr_t) node->younger, (uintptr_t) node->elder,
|
|
(uintptr_t) node->parent, node->flags, node->low, node->size);
|
|
if (!MTR_TEST(node,MTR_TERMINAL)) Mtr_PrintTree(node->child);
|
|
Mtr_PrintTree(node->younger);
|
|
return;
|
|
|
|
} /* end of Mtr_PrintTree */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of internal functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of static functions */
|
|
/*---------------------------------------------------------------------------*/
|