#include "cubes.h" /************************************************************************ NAME merge_and_link PURPOSE Once the star product on two cubes gives a result, one or both of the original cubes may be covered and have to be deleted. Also the new cube must be placed properly in the graph and the cubes deleted removed from it. SYNOPSIS struct node *merge_and_link(node0,node1,nodex) struct node **node0,**node1,*nodex; DESCRIPTION We look at node 1 and 0 to see if they are covered by nodex. A node deleted must have all its descendants and ancestors passed to the new node. The new node will have the two nodes as ancestors, or their own ancestors and descendants if they are covered. The address of the new node is returned. COORDINATES McGill University Electrical Engineering VLSI lab MONTREAL CANADA 13 july 1984 AUTHOR Michel DAGENAIS ***************************************************************************/ struct node *merge_and_link(node0,node1,nodex) struct node **node0,**node1,*nodex; { struct node *temp_node0, /* temp pointer to a node */ *temp_node1; /* temp pointer to a node */ struct parent *temp_parent; /* temp pointer to a parent just allocated */ int cover_status; /* int tells which of the two cubes are covered by the new cube nodex */ cover_status = covers(nodex->cube,(*node0)->cube); cover_status = cover_status << 1; cover_status |= covers(nodex->cube,(*node1)->cube); temp_node0 = *node0; temp_node1 = *node1; switch(cover_status) { case 0 : /* none of the cubes are covered, cubex has two ancestors and a new node will be allocated. Also the new cube is a descendant of the two others */ nodex = copy_and_alloc_node(nodex->cube); temp_parent = alloc_parent(); nodex->ancestors = temp_parent; temp_parent->parent = temp_node0; temp_parent->next_parent = alloc_parent(); (temp_parent->next_parent)->parent = temp_node1; temp_parent = alloc_parent(); temp_parent->next_parent = temp_node0->descendants; temp_node0->descendants = temp_parent; temp_parent->parent = nodex; temp_parent = alloc_parent(); temp_parent->next_parent = temp_node1->descendants; temp_node1->descendants = temp_parent; temp_parent->parent = nodex; return(nodex); case 3 : /* the two cubes are covered by nodex, nodex will be placed in the graph instead of node0 and all the ancestors and descendants of the both cubes are passed to nodex. */ temp_node0->status |= temp_node1->status; copy_cube(nodex->cube,temp_node0->cube); pass_ancestors(temp_node1,temp_node0); pass_descendants(temp_node1,temp_node0); *node0 = temp_node0->next_node; *node1 = temp_node1->next_node; free_node(temp_node1); return(temp_node0); case 2 : /* the cube0 is covered by cubex. Cubex will take its place in the graph and cube1 will be added as one of its ancestor. Also cubex will be a descendant of cube1. */ copy_cube(nodex->cube,temp_node0->cube); temp_parent = alloc_parent(); temp_parent->next_parent = temp_node0->ancestors; temp_node0->ancestors = temp_parent; temp_parent->parent = temp_node1; temp_parent = alloc_parent(); temp_parent->next_parent = temp_node1->descendants; temp_node1->descendants = temp_parent; temp_parent->parent = temp_node0; *node0 = temp_node0->next_node; return(temp_node0); case 1 : /* the cube1 is covered by cubex. Cubex will take its place in the graph and cube0 will be added as one of its ancestor. Also cubex will be a descendant of cube0. */ copy_cube(nodex->cube,temp_node1->cube); temp_parent = alloc_parent(); temp_parent->next_parent = temp_node1->ancestors; temp_node1->ancestors = temp_parent; temp_parent->parent = temp_node0; temp_parent = alloc_parent(); temp_parent->next_parent = temp_node0->descendants; temp_node0->descendants = temp_parent; temp_parent->parent = temp_node1; *node1 = temp_node1->next_node; return(temp_node1); } /* the program cannot reach here since all cases are defined and end with a return. */ fatal_program_error("internal coding error in merge and link"); return(nodex); } /************************************************************************ NAME pass_ancestors, pass_descendants PURPOSE when a node is removed from the graph, its descendants and ancestors are passed to another node and this function does it. SYNOPSIS pass_ancestors(node_from,node_to) struct node *node_from,*node_to; pass_descendants(node_from,node_to) struct node *node_from,_node_to; DESCRIPTION When a set of parents is passed from a node to another, these parents should be inserted in the list of the node_to but also these ancestors should be notified that the address of their descendant is changed. for each ancestor or descendant passed, the corresponding list of descendant or ancestor of the parent node should be scanned for the address of the node_from to be replaced by the address of the node_to. COORDINATES McGill University Electrical Engineering VLSI lab MONTREAL CANADA 13 july 1984 AUTHOR Michel DAGENAIS *************************************************************************/ pass_descendants(node_from,node_to) struct node *node_from,*node_to; { struct parent *temp_parent, /* temp pointer to the next parent in list */ *parent_to, /* temp pointer to descendant list of node_to*/ *parent_from; /* temp pointer to descendant list of nodefrom*/ parent_to = node_to->descendants; parent_from = node_from->descendants; for(; parent_from != NULL ; parent_from = temp_parent) /* for each descendant in the list, we look in the ancestor list until we find the link to the node_from , after passing it to node_to. */ { temp_parent = parent_from->next_parent; parent_from->next_parent = parent_to; parent_to = parent_from; parent_from = (parent_from->parent)->ancestors; for(; parent_from != NULL ; parent_from = parent_from->next_parent) { if(parent_from->parent == node_from)break; } /* The link to node from was not found, the graph is inconsistent and the program is probably bugged but at least it knows it */ if(parent_from == NULL) fatal_program_error("inconsistency in graph description"); /* The link to node from was found, it is changed to point now to node_to */ parent_from->parent = node_to; } node_to->descendants = parent_to; } /****************************************************************************/ pass_ancestors(node_from,node_to) struct node *node_from,*node_to; { struct parent *temp_parent, /* temp pointer to the next parent in list */ *parent_to, /* temp pointer to ancestor list of node_to*/ *parent_from; /* temp pointer to ancestor list of nodefrom*/ parent_to = node_to->ancestors; parent_from = node_from->ancestors; for(; parent_from != NULL ; parent_from = temp_parent) /* each link to ancestors is passed from node_from to node_to */ { temp_parent = parent_from->next_parent; parent_from->next_parent = parent_to; parent_to = parent_from; parent_from = (parent_from->parent)->descendants; /* for each ancestor we look in their list of descendants to find the link to node_from */ for(; parent_from != NULL ; parent_from = parent_from->next_parent) { if(parent_from->parent == node_from)break; } /* the link was not found the graph is inconsistent */ if(parent_from == NULL) fatal_user_error("inconsistency in graph description"); /* the link was found we change it to point to node_to */ parent_from->parent = node_to; } node_to->ancestors = parent_to; } /**************************************************************************** NAME remove_ancestors PURPOSE When a cube is absorbed, its ancestors must be a subset of the ancestors of the cube that absorbs it. So these ancestors are simply removed from the graph and freed, before the node itself is freed. SYNOPSIS remove_ancestors(node) struct node *node; DESCRIPTION Each ancestor in the list has its parent structure pointing to node removed in its descendant list. We scan the ancestor list of the node, remove and free the link in its ancestor and then free the link to its ancestor. COORDINATES McGill University Electrical Engineering VLSI lab MONTREAL CANADA 14 july 1984 AUTHOR Michel DAGENAIS ***************************************************************************/ remove_ancestors(node) struct node *node; { struct parent **prev_parent, /* address of pointer of parent to remove */ *temp_parent, /* parent to remove */ *parent_ancestor; /* pointer to parent in a list */ parent_ancestor = node->ancestors; for(; parent_ancestor != NULL ; parent_ancestor = parent_ancestor->next_parent) { prev_parent = &((parent_ancestor->parent)->descendants); /* for each ancestor, we look in its descendant list for a link to node */ for(; (temp_parent = *prev_parent) != NULL ;) { if(temp_parent->parent == node)break; prev_parent = &(temp_parent->next_parent); } /* the link was not found, the graph is inconsistent */ if(temp_parent == NULL) fatal_program_error("inconsistency in the graph"); /* the link is found, it is removed from the list and freed */ *prev_parent = temp_parent->next_parent; free_parent(temp_parent); } /* all the links of ancestors to the node were removed and freed, we can now free the list of ancestors. */ free_list_of_parents(&(node->ancestors)); } /**************************************************************************** NAME absorb_and_unlink PURPOSE When a cube is absorbed this function is called to remove it from the graph. SYNOPSIS int absorb_and_unlink(good_node,bad_node) struct node *good_node,**bad_node; DESCRIPTION The bad node is covered by the bad node and should be removed from the graph. Its links with ancestors will be removed since the good node has its own ancestors that anyway already include the important ancestors of the bad node. The descendants of the bad node are passed to the good node because we cannot leave those without ancestors. COORDINATES McGill University Electrical Engineering VLSI lab MONTREAL CANADA 13 july 1984 AUTHOR Michel DAGENAIS ****************************************************************************/ absorb_and_unlink(good_node,bad_node) struct node *good_node,**bad_node; { struct node *temp_node; /* temp pointer to bad_node */ temp_node = *bad_node; pass_descendants(temp_node,good_node); remove_ancestors(temp_node); good_node->status |= temp_node->status; *bad_node = temp_node->next_node; free_node(temp_node); } *