1 /**CFile***********************************************************************
7 Synopsis [Functions to support group specification for reordering.]
9 Description [External procedures included in this module:
11 <li> Mtr_InitGroupTree()
13 <li> Mtr_DissolveGroup()
16 <li> Mtr_PrintGroups()
19 Static procedures included in this module:
25 SeeAlso [cudd package]
27 Author [Fabio Somenzi]
29 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
33 Redistribution and use in source and binary forms, with or without
34 modification, are permitted provided that the following conditions
37 Redistributions of source code must retain the above copyright
38 notice, this list of conditions and the following disclaimer.
40 Redistributions in binary form must reproduce the above copyright
41 notice, this list of conditions and the following disclaimer in the
42 documentation and/or other materials provided with the distribution.
44 Neither the name of the University of Colorado nor the names of its
45 contributors may be used to endorse or promote products derived from
46 this software without specific prior written permission.
48 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
51 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
52 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
53 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
54 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
55 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
56 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
58 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 POSSIBILITY OF SUCH DAMAGE.]
61 ******************************************************************************/
66 /*---------------------------------------------------------------------------*/
67 /* Constant declarations */
68 /*---------------------------------------------------------------------------*/
70 /*---------------------------------------------------------------------------*/
71 /* Stucture declarations */
72 /*---------------------------------------------------------------------------*/
74 /*---------------------------------------------------------------------------*/
75 /* Type declarations */
76 /*---------------------------------------------------------------------------*/
78 /*---------------------------------------------------------------------------*/
79 /* Variable declarations */
80 /*---------------------------------------------------------------------------*/
83 static char rcsid
[] MTR_UNUSED
= "$Id: mtrGroup.c,v 1.18 2009/02/20 02:03:47 fabio Exp $";
86 /*---------------------------------------------------------------------------*/
87 /* Macro declarations */
88 /*---------------------------------------------------------------------------*/
90 /**AutomaticStart*************************************************************/
92 /*---------------------------------------------------------------------------*/
93 /* Static function prototypes */
94 /*---------------------------------------------------------------------------*/
96 static int mtrShiftHL (MtrNode
*node
, int shift
);
98 /**AutomaticEnd***************************************************************/
100 /*---------------------------------------------------------------------------*/
101 /* Definition of exported functions */
102 /*---------------------------------------------------------------------------*/
105 /**Function********************************************************************
107 Synopsis [Allocate new tree.]
109 Description [Allocate new tree with one node, whose low and size
110 fields are specified by the lower and size parameters.
111 Returns pointer to tree root.]
115 SeeAlso [Mtr_InitTree Mtr_FreeTree]
117 ******************************************************************************/
125 root
= Mtr_InitTree();
126 if (root
== NULL
) return(NULL
);
127 root
->flags
= MTR_DEFAULT
;
132 } /* end of Mtr_InitGroupTree */
135 /**Function********************************************************************
137 Synopsis [Makes a new group with size leaves starting at low.]
139 Description [Makes a new group with size leaves starting at low.
140 If the new group intersects an existing group, it must
141 either contain it or be contained by it. This procedure relies on
142 the low and size fields of each node. It also assumes that the
143 children of each node are sorted in order of increasing low. In
144 case of a valid request, the flags of the new group are set to the
145 value passed in `flags.' This can also be used to change the flags
146 of an existing group. Returns the pointer to the root of the new
147 group upon successful termination; NULL otherwise. If the group
148 already exists, the pointer to its root is returned.]
152 SeeAlso [Mtr_DissolveGroup Mtr_ReadGroups Mtr_FindGroup]
154 ******************************************************************************/
157 MtrNode
* root
/* root of the group tree */,
158 unsigned int low
/* lower bound of the group */,
159 unsigned int size
/* upper bound of the group */,
160 unsigned int flags
/* flags for the new group */)
172 /* Check whether current group includes new group. This check is
173 ** necessary at the top-level call. In the subsequent calls it is
175 if (low
< (unsigned int) root
->low
||
176 low
+ size
> (unsigned int) (root
->low
+ root
->size
))
179 /* Trying to create an existing group has the effect of updating
181 if (root
->size
== size
&& root
->low
== low
) {
186 /* At this point we know that the new group is properly contained
187 ** in the group of root. We have two possible cases here: - root
188 ** is a terminal node; - root has children. */
190 /* Root has no children: create a new group. */
191 if (root
->child
== NULL
) {
192 newn
= Mtr_AllocNode();
193 if (newn
== NULL
) return(NULL
); /* out of memory */
198 newn
->elder
= newn
->younger
= newn
->child
= NULL
;
203 /* Root has children: Find all chidren of root that are included
204 ** in the new group. If the group of any child entirely contains
205 ** the new group, call Mtr_MakeGroup recursively. */
207 first
= root
->child
; /* guaranteed to be non-NULL */
208 while (first
!= NULL
&& low
>= (unsigned int) (first
->low
+ first
->size
)) {
210 first
= first
->younger
;
213 /* We have scanned the entire list and we need to append a new
214 ** child at the end of it. Previous points to the last child
216 newn
= Mtr_AllocNode();
217 if (newn
== NULL
) return(NULL
); /* out of memory */
222 newn
->elder
= previous
;
223 previous
->younger
= newn
;
224 newn
->younger
= newn
->child
= NULL
;
227 /* Here first is non-NULL and low < first->low + first->size. */
228 if (low
>= (unsigned int) first
->low
&&
229 low
+ size
<= (unsigned int) (first
->low
+ first
->size
)) {
230 /* The new group is contained in the group of first. */
231 newn
= Mtr_MakeGroup(first
, low
, size
, flags
);
233 } else if (low
+ size
<= first
->low
) {
234 /* The new group is entirely contained in the gap between
235 ** previous and first. */
236 newn
= Mtr_AllocNode();
237 if (newn
== NULL
) return(NULL
); /* out of memory */
243 newn
->elder
= previous
;
244 newn
->younger
= first
;
246 if (previous
!= NULL
) {
247 previous
->younger
= newn
;
252 } else if (low
< (unsigned int) first
->low
&&
253 low
+ size
< (unsigned int) (first
->low
+ first
->size
)) {
254 /* Trying to cut an existing group: not allowed. */
256 } else if (low
> first
->low
) {
257 /* The new group neither is contained in the group of first
258 ** (this was tested above) nor contains it. It is therefore
259 ** trying to cut an existing group: not allowed. */
263 /* First holds the pointer to the first child contained in the new
264 ** group. Here low <= first->low and low + size >= first->low +
265 ** first->size. One of the two inequalities is strict. */
266 last
= first
->younger
;
267 while (last
!= NULL
&&
268 (unsigned int) (last
->low
+ last
->size
) < low
+ size
) {
269 last
= last
->younger
;
272 /* All the chilren of root from first onward become children
273 ** of the new group. */
274 newn
= Mtr_AllocNode();
275 if (newn
== NULL
) return(NULL
); /* out of memory */
281 newn
->elder
= previous
;
282 newn
->younger
= NULL
;
284 if (previous
!= NULL
) {
285 previous
->younger
= newn
;
290 while (last
!= NULL
) {
292 last
= last
->younger
;
297 /* Here last != NULL and low + size <= last->low + last->size. */
298 if (low
+ size
- 1 >= (unsigned int) last
->low
&&
299 low
+ size
< (unsigned int) (last
->low
+ last
->size
)) {
300 /* Trying to cut an existing group: not allowed. */
304 /* First and last point to the first and last of the children of
305 ** root that are included in the new group. Allocate a new node
306 ** and make all children of root between first and last chidren of
307 ** the new node. Previous points to the child of root immediately
308 ** preceeding first. If it is NULL, then first is the first child
310 newn
= Mtr_AllocNode();
311 if (newn
== NULL
) return(NULL
); /* out of memory */
317 if (previous
== NULL
) {
320 previous
->younger
= newn
;
322 newn
->elder
= previous
;
323 newn
->younger
= last
->younger
;
324 if (last
->younger
!= NULL
) {
325 last
->younger
->elder
= newn
;
327 last
->younger
= NULL
;
329 for (node
= first
; node
!= NULL
; node
= node
->younger
) {
335 } /* end of Mtr_MakeGroup */
338 /**Function********************************************************************
340 Synopsis [Merges the children of `group' with the children of its
343 Description [Merges the children of `group' with the children of its
344 parent. Disposes of the node pointed by group. If group is the
345 root of the group tree, this procedure leaves the tree unchanged.
346 Returns the pointer to the parent of `group' upon successful
347 termination; NULL otherwise.]
351 SeeAlso [Mtr_MakeGroup]
353 ******************************************************************************/
356 MtrNode
* group
/* group to be dissolved */)
361 parent
= group
->parent
;
363 if (parent
== NULL
) return(NULL
);
364 if (MTR_TEST(group
,MTR_TERMINAL
) || group
->child
== NULL
) return(NULL
);
366 /* Make all children of group children of its parent, and make
367 ** last point to the last child of group. */
368 for (last
= group
->child
; last
->younger
!= NULL
; last
= last
->younger
) {
369 last
->parent
= parent
;
371 last
->parent
= parent
;
373 last
->younger
= group
->younger
;
374 if (group
->younger
!= NULL
) {
375 group
->younger
->elder
= last
;
378 group
->child
->elder
= group
->elder
;
379 if (group
== parent
->child
) {
380 parent
->child
= group
->child
;
382 group
->elder
->younger
= group
->child
;
385 Mtr_DeallocNode(group
);
388 } /* end of Mtr_DissolveGroup */
391 /**Function********************************************************************
393 Synopsis [Finds a group with size leaves starting at low, if it exists.]
395 Description [Finds a group with size leaves starting at low, if it
396 exists. This procedure relies on the low and size fields of each
397 node. It also assumes that the children of each node are sorted in
398 order of increasing low. Returns the pointer to the root of the
399 group upon successful termination; NULL otherwise.]
405 ******************************************************************************/
408 MtrNode
* root
/* root of the group tree */,
409 unsigned int low
/* lower bound of the group */,
410 unsigned int size
/* upper bound of the group */)
415 /* We cannot have a non-empty proper subgroup of a singleton set. */
416 assert(!MTR_TEST(root
,MTR_TERMINAL
));
420 if (size
< 1) return(NULL
);
422 /* Check whether current group includes the group sought. This
423 ** check is necessary at the top-level call. In the subsequent
424 ** calls it is redundant. */
425 if (low
< (unsigned int) root
->low
||
426 low
+ size
> (unsigned int) (root
->low
+ root
->size
))
429 if (root
->size
== size
&& root
->low
== low
)
432 if (root
->child
== NULL
)
435 /* Find all chidren of root that are included in the new group. If
436 ** the group of any child entirely contains the new group, call
437 ** Mtr_MakeGroup recursively. */
439 while (low
>= (unsigned int) (node
->low
+ node
->size
)) {
440 node
= node
->younger
;
442 if (low
+ size
<= (unsigned int) (node
->low
+ node
->size
)) {
443 /* The group is contained in the group of node. */
444 node
= Mtr_FindGroup(node
, low
, size
);
450 } /* end of Mtr_FindGroup */
453 /**Function********************************************************************
455 Synopsis [Swaps two children of a tree node.]
457 Description [Swaps two children of a tree node. Adjusts the high and
458 low fields of the two nodes and their descendants. The two children
459 must be adjacent. However, first may be the younger sibling of second.
460 Returns 1 in case of success; 0 otherwise.]
466 ******************************************************************************/
469 MtrNode
* first
/* first node to be swapped */,
470 MtrNode
* second
/* second node to be swapped */)
477 if (second
->younger
== first
) { /* make first first */
481 } else if (first
->younger
!= second
) { /* non-adjacent */
485 sizeFirst
= first
->size
;
486 sizeSecond
= second
->size
;
488 /* Swap the two nodes. */
489 parent
= first
->parent
;
490 if (parent
== NULL
|| second
->parent
!= parent
) return(0);
491 if (parent
->child
== first
) {
492 parent
->child
= second
;
493 } else { /* first->elder != NULL */
494 first
->elder
->younger
= second
;
496 if (second
->younger
!= NULL
) {
497 second
->younger
->elder
= first
;
499 first
->younger
= second
->younger
;
500 second
->elder
= first
->elder
;
501 first
->elder
= second
;
502 second
->younger
= first
;
504 /* Adjust the high and low fields. */
505 if (!mtrShiftHL(first
,sizeSecond
)) return(0);
506 if (!mtrShiftHL(second
,-sizeFirst
)) return(0);
510 } /* end of Mtr_SwapGroups */
513 /**Function********************************************************************
515 Synopsis [Prints the groups as a parenthesized list.]
517 Description [Prints the groups as a parenthesized list. After each
518 group, the group's flag are printed, preceded by a `|'. For each
519 flag (except MTR_TERMINAL) a character is printed.
525 The second argument, silent, if different from 0, causes
526 Mtr_PrintGroups to only check the syntax of the group tree.
531 SeeAlso [Mtr_PrintTree]
533 ******************************************************************************/
536 MtrNode
* root
/* root of the group tree */,
537 int silent
/* flag to check tree syntax only */)
541 assert(root
!= NULL
);
542 assert(root
->younger
== NULL
|| root
->younger
->elder
== root
);
543 assert(root
->elder
== NULL
|| root
->elder
->younger
== root
);
544 #if SIZEOF_VOID_P == 8
545 if (!silent
) (void) printf("(%u",root
->low
);
547 if (!silent
) (void) printf("(%hu",root
->low
);
549 if (MTR_TEST(root
,MTR_TERMINAL
) || root
->child
== NULL
) {
550 if (!silent
) (void) printf(",");
553 while (node
!= NULL
) {
554 assert(node
->low
>= root
->low
&& (int) (node
->low
+ node
->size
) <= (int) (root
->low
+ root
->size
));
555 assert(node
->parent
== root
);
556 Mtr_PrintGroups(node
,silent
);
557 node
= node
->younger
;
561 #if SIZEOF_VOID_P == 8
562 (void) printf("%u", root
->low
+ root
->size
- 1);
564 (void) printf("%hu", root
->low
+ root
->size
- 1);
566 if (root
->flags
!= MTR_DEFAULT
) {
568 if (MTR_TEST(root
,MTR_FIXED
)) (void) printf("F");
569 if (MTR_TEST(root
,MTR_NEWNODE
)) (void) printf("N");
570 if (MTR_TEST(root
,MTR_SOFT
)) (void) printf("S");
573 if (root
->parent
== NULL
) (void) printf("\n");
575 assert((root
->flags
&~(MTR_TERMINAL
| MTR_SOFT
| MTR_FIXED
| MTR_NEWNODE
)) == 0);
578 } /* end of Mtr_PrintGroups */
581 /**Function********************************************************************
583 Synopsis [Reads groups from a file and creates a group tree.]
585 Description [Reads groups from a file and creates a group tree.
586 Each group is specified by three fields:
590 Low and size are (short) integers. Flags is a string composed of the
591 following characters (with associated translation):
599 Normally, the only flags that are needed are D and F. Groups and
600 fields are separated by white space (spaces, tabs, and newlines).
601 Returns a pointer to the group tree if successful; NULL otherwise.]
605 SeeAlso [Mtr_InitGroupTree Mtr_MakeGroup]
607 ******************************************************************************/
610 FILE * fp
/* file pointer */,
611 int nleaves
/* number of leaves of the new tree */)
619 char attrib
[8*sizeof(unsigned int)+1];
622 root
= Mtr_InitGroupTree(0,nleaves
);
623 if (root
== NULL
) return NULL
;
626 /* Read a triple and check for consistency. */
627 err
= fscanf(fp
, "%d %d %s", &low
, &size
, attrib
);
630 } else if (err
!= 3) {
633 } else if (low
< 0 || low
+size
> nleaves
|| size
< 1) {
636 } else if (strlen(attrib
) > 8 * sizeof(MtrHalfWord
)) {
637 /* Not enough bits in the flags word to store these many
643 /* Parse the flag string. Currently all flags are permitted,
644 ** to make debugging easier. Normally, specifying NEWNODE
645 ** wouldn't be allowed. */
647 for (c
=attrib
; *c
!= 0; c
++) {
655 flags
|= MTR_NEWNODE
;
661 flags
|= MTR_TERMINAL
;
667 node
= Mtr_MakeGroup(root
, (MtrHalfWord
) low
, (MtrHalfWord
) size
,
677 } /* end of Mtr_ReadGroups */
680 /*---------------------------------------------------------------------------*/
681 /* Definition of internal functions */
682 /*---------------------------------------------------------------------------*/
684 /*---------------------------------------------------------------------------*/
685 /* Definition of static functions */
686 /*---------------------------------------------------------------------------*/
689 /**Function********************************************************************
691 Synopsis [Adjusts the low fields of a node and its descendants.]
693 Description [Adjusts the low fields of a node and its
694 descendants. Adds shift to low of each node. Checks that no
695 out-of-bounds values result. Returns 1 in case of success; 0
702 ******************************************************************************/
705 MtrNode
* node
/* group tree node */,
706 int shift
/* amount by which low should be changed */)
711 low
= (int) node
->low
;
716 if (low
< 0 || low
+ (int) (node
->size
- 1) > (int) MTR_MAXHIGH
) return(0);
718 node
->low
= (MtrHalfWord
) low
;
720 if (!MTR_TEST(node
,MTR_TERMINAL
) && node
->child
!= NULL
) {
721 auxnode
= node
->child
;
723 if (!mtrShiftHL(auxnode
,shift
)) return(0);
724 auxnode
= auxnode
->younger
;
725 } while (auxnode
!= NULL
);
730 } /* end of mtrShiftHL */