00001
00037 #include "util_hack.h"
00038 #include "cuddInt.h"
00039
00040
00041
00042
00043
00044 #define CUDD_SWAP_MOVE 0
00045 #define CUDD_LINEAR_TRANSFORM_MOVE 1
00046 #define CUDD_INVERSE_TRANSFORM_MOVE 2
00047 #if SIZEOF_LONG == 8
00048 #define BPL 64
00049 #define LOGBPL 6
00050 #else
00051 #define BPL 32
00052 #define LOGBPL 5
00053 #endif
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 #ifndef lint
00068 static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $";
00069 #endif
00070
00071 static int *entry;
00072
00073 #ifdef DD_STATS
00074 extern int ddTotalNumberSwapping;
00075 extern int ddTotalNISwaps;
00076 static int ddTotalNumberLinearTr;
00077 #endif
00078
00079 #ifdef DD_DEBUG
00080 static int zero = 0;
00081 #endif
00082
00083
00084
00085
00086
00089
00090
00091
00092
00093 static int ddLinearUniqueCompare ARGS((int *ptrX, int *ptrY));
00094 static int ddLinearAndSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh));
00095 static Move * ddLinearAndSiftingUp ARGS((DdManager *table, int y, int xLow, Move *prevMoves));
00096 static Move * ddLinearAndSiftingDown ARGS((DdManager *table, int x, int xHigh, Move *prevMoves));
00097 static int ddLinearAndSiftingBackward ARGS((DdManager *table, int size, Move *moves));
00098 static Move* ddUndoMoves ARGS((DdManager *table, Move *moves));
00099 static int cuddLinearInPlace ARGS((DdManager *table, int x, int y));
00100 static void ddUpdateInteractionMatrix ARGS((DdManager *table, int xindex, int yindex));
00101 static int cuddInitLinear ARGS((DdManager *table));
00102 static int cuddResizeLinear ARGS((DdManager *table));
00103 static void cuddXorLinear ARGS((DdManager *table, int x, int y));
00104
00108
00109
00110
00111
00112
00125 int
00126 Cudd_PrintLinear(
00127 DdManager * table)
00128 {
00129 int i,j,k;
00130 int retval;
00131 int nvars = table->linearSize;
00132 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00133 long word;
00134
00135 for (i = 0; i < nvars; i++) {
00136 for (j = 0; j < wordsPerRow; j++) {
00137 word = table->linear[i*wordsPerRow + j];
00138 for (k = 0; k < BPL; k++) {
00139 retval = fprintf(table->out,"%ld",word & 1);
00140 if (retval == 0) return(0);
00141 word >>= 1;
00142 }
00143 }
00144 retval = fprintf(table->out,"\n");
00145 if (retval == 0) return(0);
00146 }
00147 return(1);
00148
00149 }
00150
00151
00163 int
00164 Cudd_ReadLinear(
00165 DdManager * table ,
00166 int x ,
00167 int y )
00168 {
00169 int nvars = table->size;
00170 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00171 long word;
00172 int bit;
00173 int result;
00174
00175 assert(table->size == table->linearSize);
00176
00177 word = wordsPerRow * x + (y >> LOGBPL);
00178 bit = y & (BPL-1);
00179 result = (int) ((table->linear[word] >> bit) & 1);
00180 return(result);
00181
00182 }
00183
00184
00185
00186
00187
00188
00189
00212 int
00213 cuddLinearAndSifting(
00214 DdManager * table,
00215 int lower,
00216 int upper)
00217 {
00218 int i;
00219 int *var;
00220 int size;
00221 int x;
00222 int result;
00223 #ifdef DD_STATS
00224 int previousSize;
00225 #endif
00226
00227 #ifdef DD_STATS
00228 ddTotalNumberLinearTr = 0;
00229 #endif
00230
00231 size = table->size;
00232
00233 var = NULL;
00234 entry = NULL;
00235 if (table->linear == NULL) {
00236 result = cuddInitLinear(table);
00237 if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00238 #if 0
00239 (void) fprintf(table->out,"\n");
00240 result = Cudd_PrintLinear(table);
00241 if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00242 #endif
00243 } else if (table->size != table->linearSize) {
00244 result = cuddResizeLinear(table);
00245 if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00246 #if 0
00247 (void) fprintf(table->out,"\n");
00248 result = Cudd_PrintLinear(table);
00249 if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00250 #endif
00251 }
00252
00253
00254 entry = ALLOC(int,size);
00255 if (entry == NULL) {
00256 table->errorCode = CUDD_MEMORY_OUT;
00257 goto cuddLinearAndSiftingOutOfMem;
00258 }
00259 var = ALLOC(int,size);
00260 if (var == NULL) {
00261 table->errorCode = CUDD_MEMORY_OUT;
00262 goto cuddLinearAndSiftingOutOfMem;
00263 }
00264
00265 for (i = 0; i < size; i++) {
00266 x = table->perm[i];
00267 entry[i] = table->subtables[x].keys;
00268 var[i] = i;
00269 }
00270
00271 qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddLinearUniqueCompare);
00272
00273
00274 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00275 x = table->perm[var[i]];
00276 if (x < lower || x > upper) continue;
00277 #ifdef DD_STATS
00278 previousSize = table->keys - table->isolated;
00279 #endif
00280 result = ddLinearAndSiftingAux(table,x,lower,upper);
00281 if (!result) goto cuddLinearAndSiftingOutOfMem;
00282 #ifdef DD_STATS
00283 if (table->keys < (unsigned) previousSize + table->isolated) {
00284 (void) fprintf(table->out,"-");
00285 } else if (table->keys > (unsigned) previousSize + table->isolated) {
00286 (void) fprintf(table->out,"+");
00287 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
00288 } else {
00289 (void) fprintf(table->out,"=");
00290 }
00291 fflush(table->out);
00292 #endif
00293 #ifdef DD_DEBUG
00294 (void) Cudd_DebugCheck(table);
00295 #endif
00296 }
00297
00298 FREE(var);
00299 FREE(entry);
00300
00301 #ifdef DD_STATS
00302 (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.",
00303 ddTotalNumberLinearTr);
00304 #endif
00305
00306 return(1);
00307
00308 cuddLinearAndSiftingOutOfMem:
00309
00310 if (entry != NULL) FREE(entry);
00311 if (var != NULL) FREE(var);
00312
00313 return(0);
00314
00315 }
00316
00317
00318
00319
00320
00321
00322
00335 static int
00336 ddLinearUniqueCompare(
00337 int * ptrX,
00338 int * ptrY)
00339 {
00340 #if 0
00341 if (entry[*ptrY] == entry[*ptrX]) {
00342 return((*ptrX) - (*ptrY));
00343 }
00344 #endif
00345 return(entry[*ptrY] - entry[*ptrX]);
00346
00347 }
00348
00349
00363 static int
00364 ddLinearAndSiftingAux(
00365 DdManager * table,
00366 int x,
00367 int xLow,
00368 int xHigh)
00369 {
00370
00371 Move *move;
00372 Move *moveUp;
00373 Move *moveDown;
00374 int initialSize;
00375 int result;
00376
00377 initialSize = table->keys - table->isolated;
00378
00379 moveDown = NULL;
00380 moveUp = NULL;
00381
00382 if (x == xLow) {
00383 moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
00384
00385 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00386
00387 result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
00388 if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00389
00390 } else if (x == xHigh) {
00391 moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
00392
00393 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00394
00395 result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
00396 if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00397
00398 } else if ((x - xLow) > (xHigh - x)) {
00399 moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
00400
00401 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00402 moveUp = ddUndoMoves(table,moveDown);
00403 #ifdef DD_DEBUG
00404 assert(moveUp == NULL || moveUp->x == x);
00405 #endif
00406 moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp);
00407 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00408
00409 result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
00410 if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00411
00412 } else {
00413 moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
00414
00415 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00416 moveDown = ddUndoMoves(table,moveUp);
00417 #ifdef DD_DEBUG
00418 assert(moveDown == NULL || moveDown->y == x);
00419 #endif
00420 moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown);
00421 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00422
00423 result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
00424 if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00425 }
00426
00427 while (moveDown != NULL) {
00428 move = moveDown->next;
00429 cuddDeallocNode(table, (DdNode *) moveDown);
00430 moveDown = move;
00431 }
00432 while (moveUp != NULL) {
00433 move = moveUp->next;
00434 cuddDeallocNode(table, (DdNode *) moveUp);
00435 moveUp = move;
00436 }
00437
00438 return(1);
00439
00440 ddLinearAndSiftingAuxOutOfMem:
00441 while (moveDown != NULL) {
00442 move = moveDown->next;
00443 cuddDeallocNode(table, (DdNode *) moveDown);
00444 moveDown = move;
00445 }
00446 while (moveUp != NULL) {
00447 move = moveUp->next;
00448 cuddDeallocNode(table, (DdNode *) moveUp);
00449 moveUp = move;
00450 }
00451
00452 return(0);
00453
00454 }
00455
00456
00469 static Move *
00470 ddLinearAndSiftingUp(
00471 DdManager * table,
00472 int y,
00473 int xLow,
00474 Move * prevMoves)
00475 {
00476 Move *moves;
00477 Move *move;
00478 int x;
00479 int size, newsize;
00480 int limitSize;
00481 int xindex, yindex;
00482 int isolated;
00483 int L;
00484 #ifdef DD_DEBUG
00485 int checkL;
00486 int z;
00487 int zindex;
00488 #endif
00489
00490 moves = prevMoves;
00491 yindex = table->invperm[y];
00492
00493
00494
00495
00496
00497
00498
00499 limitSize = L = table->keys - table->isolated;
00500 for (x = xLow + 1; x < y; x++) {
00501 xindex = table->invperm[x];
00502 if (cuddTestInteract(table,xindex,yindex)) {
00503 isolated = table->vars[xindex]->ref == 1;
00504 L -= table->subtables[x].keys - isolated;
00505 }
00506 }
00507 isolated = table->vars[yindex]->ref == 1;
00508 L -= table->subtables[y].keys - isolated;
00509
00510 x = cuddNextLow(table,y);
00511 while (x >= xLow && L <= limitSize) {
00512 xindex = table->invperm[x];
00513 #ifdef DD_DEBUG
00514 checkL = table->keys - table->isolated;
00515 for (z = xLow + 1; z < y; z++) {
00516 zindex = table->invperm[z];
00517 if (cuddTestInteract(table,zindex,yindex)) {
00518 isolated = table->vars[zindex]->ref == 1;
00519 checkL -= table->subtables[z].keys - isolated;
00520 }
00521 }
00522 isolated = table->vars[yindex]->ref == 1;
00523 checkL -= table->subtables[y].keys - isolated;
00524 if (L != checkL) {
00525 (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L);
00526 }
00527 #endif
00528 size = cuddSwapInPlace(table,x,y);
00529 if (size == 0) goto ddLinearAndSiftingUpOutOfMem;
00530 newsize = cuddLinearInPlace(table,x,y);
00531 if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
00532 move = (Move *) cuddDynamicAllocNode(table);
00533 if (move == NULL) goto ddLinearAndSiftingUpOutOfMem;
00534 move->x = x;
00535 move->y = y;
00536 move->next = moves;
00537 moves = move;
00538 move->flags = CUDD_SWAP_MOVE;
00539 if (newsize >= size) {
00540
00541
00542
00543
00544 newsize = cuddLinearInPlace(table,x,y);
00545 if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
00546 #ifdef DD_DEBUG
00547 if (newsize != size) {
00548 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
00549 }
00550 #endif
00551 } else if (cuddTestInteract(table,xindex,yindex)) {
00552 size = newsize;
00553 move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
00554 ddUpdateInteractionMatrix(table,xindex,yindex);
00555 }
00556 move->size = size;
00557
00558 if (cuddTestInteract(table,xindex,yindex)) {
00559 isolated = table->vars[xindex]->ref == 1;
00560 L += table->subtables[y].keys - isolated;
00561 }
00562 if ((double) size > (double) limitSize * table->maxGrowth) break;
00563 if (size < limitSize) limitSize = size;
00564 y = x;
00565 x = cuddNextLow(table,y);
00566 }
00567 return(moves);
00568
00569 ddLinearAndSiftingUpOutOfMem:
00570 while (moves != NULL) {
00571 move = moves->next;
00572 cuddDeallocNode(table, (DdNode *) moves);
00573 moves = move;
00574 }
00575 return((Move *) CUDD_OUT_OF_MEM);
00576
00577 }
00578
00579
00592 static Move *
00593 ddLinearAndSiftingDown(
00594 DdManager * table,
00595 int x,
00596 int xHigh,
00597 Move * prevMoves)
00598 {
00599 Move *moves;
00600 Move *move;
00601 int y;
00602 int size, newsize;
00603 int R;
00604 int limitSize;
00605 int xindex, yindex;
00606 int isolated;
00607 #ifdef DD_DEBUG
00608 int checkR;
00609 int z;
00610 int zindex;
00611 #endif
00612
00613 moves = prevMoves;
00614
00615 xindex = table->invperm[x];
00616 limitSize = size = table->keys - table->isolated;
00617 R = 0;
00618 for (y = xHigh; y > x; y--) {
00619 yindex = table->invperm[y];
00620 if (cuddTestInteract(table,xindex,yindex)) {
00621 isolated = table->vars[yindex]->ref == 1;
00622 R += table->subtables[y].keys - isolated;
00623 }
00624 }
00625
00626 y = cuddNextHigh(table,x);
00627 while (y <= xHigh && size - R < limitSize) {
00628 #ifdef DD_DEBUG
00629 checkR = 0;
00630 for (z = xHigh; z > x; z--) {
00631 zindex = table->invperm[z];
00632 if (cuddTestInteract(table,xindex,zindex)) {
00633 isolated = table->vars[zindex]->ref == 1;
00634 checkR += table->subtables[z].keys - isolated;
00635 }
00636 }
00637 if (R != checkR) {
00638 (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R);
00639 }
00640 #endif
00641
00642 yindex = table->invperm[y];
00643 if (cuddTestInteract(table,xindex,yindex)) {
00644 isolated = table->vars[yindex]->ref == 1;
00645 R -= table->subtables[y].keys - isolated;
00646 }
00647 size = cuddSwapInPlace(table,x,y);
00648 if (size == 0) goto ddLinearAndSiftingDownOutOfMem;
00649 newsize = cuddLinearInPlace(table,x,y);
00650 if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
00651 move = (Move *) cuddDynamicAllocNode(table);
00652 if (move == NULL) goto ddLinearAndSiftingDownOutOfMem;
00653 move->x = x;
00654 move->y = y;
00655 move->next = moves;
00656 moves = move;
00657 move->flags = CUDD_SWAP_MOVE;
00658 if (newsize >= size) {
00659
00660
00661
00662
00663 newsize = cuddLinearInPlace(table,x,y);
00664 if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
00665 if (newsize != size) {
00666 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
00667 }
00668 } else if (cuddTestInteract(table,xindex,yindex)) {
00669 size = newsize;
00670 move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
00671 ddUpdateInteractionMatrix(table,xindex,yindex);
00672 }
00673 move->size = size;
00674 if ((double) size > (double) limitSize * table->maxGrowth) break;
00675 if (size < limitSize) limitSize = size;
00676 x = y;
00677 y = cuddNextHigh(table,x);
00678 }
00679 return(moves);
00680
00681 ddLinearAndSiftingDownOutOfMem:
00682 while (moves != NULL) {
00683 move = moves->next;
00684 cuddDeallocNode(table, (DdNode *) moves);
00685 moves = move;
00686 }
00687 return((Move *) CUDD_OUT_OF_MEM);
00688
00689 }
00690
00691
00705 static int
00706 ddLinearAndSiftingBackward(
00707 DdManager * table,
00708 int size,
00709 Move * moves)
00710 {
00711 Move *move;
00712 int res;
00713
00714 for (move = moves; move != NULL; move = move->next) {
00715 if (move->size < size) {
00716 size = move->size;
00717 }
00718 }
00719
00720 for (move = moves; move != NULL; move = move->next) {
00721 if (move->size == size) return(1);
00722 if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
00723 res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
00724 if (!res) return(0);
00725 }
00726 res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
00727 if (!res) return(0);
00728 if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
00729 res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
00730 if (!res) return(0);
00731 }
00732 }
00733
00734 return(1);
00735
00736 }
00737
00738
00751 static Move*
00752 ddUndoMoves(
00753 DdManager * table,
00754 Move * moves)
00755 {
00756 Move *invmoves = NULL;
00757 Move *move;
00758 Move *invmove;
00759 int size;
00760
00761 for (move = moves; move != NULL; move = move->next) {
00762 invmove = (Move *) cuddDynamicAllocNode(table);
00763 if (invmove == NULL) goto ddUndoMovesOutOfMem;
00764 invmove->x = move->x;
00765 invmove->y = move->y;
00766 invmove->next = invmoves;
00767 invmoves = invmove;
00768 if (move->flags == CUDD_SWAP_MOVE) {
00769 invmove->flags = CUDD_SWAP_MOVE;
00770 size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
00771 if (!size) goto ddUndoMovesOutOfMem;
00772 } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
00773 invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE;
00774 size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
00775 if (!size) goto ddUndoMovesOutOfMem;
00776 size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
00777 if (!size) goto ddUndoMovesOutOfMem;
00778 } else {
00779 #ifdef DD_DEBUG
00780 (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
00781 #endif
00782 invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
00783 size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
00784 if (!size) goto ddUndoMovesOutOfMem;
00785 size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
00786 if (!size) goto ddUndoMovesOutOfMem;
00787 }
00788 invmove->size = size;
00789 }
00790
00791 return(invmoves);
00792
00793 ddUndoMovesOutOfMem:
00794 while (invmoves != NULL) {
00795 move = invmoves->next;
00796 cuddDeallocNode(table, (DdNode *) invmoves);
00797 invmoves = move;
00798 }
00799 return((Move *) CUDD_OUT_OF_MEM);
00800
00801 }
00802
00803
00822 static int
00823 cuddLinearInPlace(
00824 DdManager * table,
00825 int x,
00826 int y)
00827 {
00828 DdNodePtr *xlist, *ylist;
00829 int xindex, yindex;
00830 int xslots, yslots;
00831 int xshift, yshift;
00832 int oldxkeys, oldykeys;
00833 int newxkeys, newykeys;
00834 int comple, newcomplement;
00835 int i;
00836 int posn;
00837 int isolated;
00838 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
00839 DdNode *g,*next,*last;
00840 DdNodePtr *previousP;
00841 DdNode *tmp;
00842 DdNode *sentinel = &(table->sentinel);
00843 #if DD_DEBUG
00844 int count, idcheck;
00845 #endif
00846
00847 #ifdef DD_DEBUG
00848 assert(x < y);
00849 assert(cuddNextHigh(table,x) == y);
00850 assert(table->subtables[x].keys != 0);
00851 assert(table->subtables[y].keys != 0);
00852 assert(table->subtables[x].dead == 0);
00853 assert(table->subtables[y].dead == 0);
00854 #endif
00855
00856 xindex = table->invperm[x];
00857 yindex = table->invperm[y];
00858
00859 if (cuddTestInteract(table,xindex,yindex)) {
00860 #ifdef DD_STATS
00861 ddTotalNumberLinearTr++;
00862 #endif
00863
00864 xlist = table->subtables[x].nodelist;
00865 oldxkeys = table->subtables[x].keys;
00866 xslots = table->subtables[x].slots;
00867 xshift = table->subtables[x].shift;
00868
00869
00870 ylist = table->subtables[y].nodelist;
00871 oldykeys = table->subtables[y].keys;
00872 yslots = table->subtables[y].slots;
00873 yshift = table->subtables[y].shift;
00874
00875 newxkeys = 0;
00876 newykeys = oldykeys;
00877
00878
00879
00880
00881
00882
00883
00884 isolated = - ((table->vars[xindex]->ref == 1) +
00885 (table->vars[yindex]->ref == 1));
00886
00887
00888
00889
00890
00891 g = NULL;
00892 for (i = 0; i < xslots; i++) {
00893 f = xlist[i];
00894 if (f == sentinel) continue;
00895 xlist[i] = sentinel;
00896 if (g == NULL) {
00897 g = f;
00898 } else {
00899 last->next = f;
00900 }
00901 while ((next = f->next) != sentinel) {
00902 f = next;
00903 }
00904 last = f;
00905 }
00906 last->next = NULL;
00907
00908 #ifdef DD_COUNT
00909 table->swapSteps += oldxkeys;
00910 #endif
00911
00912
00913
00914 f = g;
00915 while (f != NULL) {
00916 next = f->next;
00917
00918 f1 = cuddT(f);
00919 #ifdef DD_DEBUG
00920 assert(!(Cudd_IsComplement(f1)));
00921 #endif
00922 if ((int) f1->index == yindex) {
00923 f11 = cuddT(f1); f10 = cuddE(f1);
00924 } else {
00925 f11 = f10 = f1;
00926 }
00927 #ifdef DD_DEBUG
00928 assert(!(Cudd_IsComplement(f11)));
00929 #endif
00930 f0 = cuddE(f);
00931 comple = Cudd_IsComplement(f0);
00932 f0 = Cudd_Regular(f0);
00933 if ((int) f0->index == yindex) {
00934 f01 = cuddT(f0); f00 = cuddE(f0);
00935 } else {
00936 f01 = f00 = f0;
00937 }
00938 if (comple) {
00939 f01 = Cudd_Not(f01);
00940 f00 = Cudd_Not(f00);
00941 }
00942
00943 cuddSatDec(f1->ref);
00944
00945 if (f11 == f00) {
00946 newf1 = f11;
00947 cuddSatInc(newf1->ref);
00948 } else {
00949
00950 posn = ddHash(f11, f00, yshift);
00951
00952 previousP = &(ylist[posn]);
00953 newf1 = *previousP;
00954 while (f11 < cuddT(newf1)) {
00955 previousP = &(newf1->next);
00956 newf1 = *previousP;
00957 }
00958 while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) {
00959 previousP = &(newf1->next);
00960 newf1 = *previousP;
00961 }
00962 if (cuddT(newf1) == f11 && cuddE(newf1) == f00) {
00963 cuddSatInc(newf1->ref);
00964 } else {
00965 newf1 = cuddDynamicAllocNode(table);
00966 if (newf1 == NULL)
00967 goto cuddLinearOutOfMem;
00968 newf1->index = yindex; newf1->ref = 1;
00969 cuddT(newf1) = f11;
00970 cuddE(newf1) = f00;
00971
00972
00973
00974 newykeys++;
00975 newf1->next = *previousP;
00976 *previousP = newf1;
00977 cuddSatInc(f11->ref);
00978 tmp = Cudd_Regular(f00);
00979 cuddSatInc(tmp->ref);
00980 }
00981 }
00982 cuddT(f) = newf1;
00983 #ifdef DD_DEBUG
00984 assert(!(Cudd_IsComplement(newf1)));
00985 #endif
00986
00987
00988
00989 tmp = Cudd_Regular(f0);
00990 cuddSatDec(tmp->ref);
00991
00992 if (f01 == f10) {
00993 newf0 = f01;
00994 tmp = Cudd_Regular(newf0);
00995 cuddSatInc(tmp->ref);
00996 } else {
00997
00998 newcomplement = Cudd_IsComplement(f01);
00999 if (newcomplement) {
01000 f01 = Cudd_Not(f01);
01001 f10 = Cudd_Not(f10);
01002 }
01003
01004 posn = ddHash(f01, f10, yshift);
01005
01006 previousP = &(ylist[posn]);
01007 newf0 = *previousP;
01008 while (f01 < cuddT(newf0)) {
01009 previousP = &(newf0->next);
01010 newf0 = *previousP;
01011 }
01012 while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) {
01013 previousP = &(newf0->next);
01014 newf0 = *previousP;
01015 }
01016 if (cuddT(newf0) == f01 && cuddE(newf0) == f10) {
01017 cuddSatInc(newf0->ref);
01018 } else {
01019 newf0 = cuddDynamicAllocNode(table);
01020 if (newf0 == NULL)
01021 goto cuddLinearOutOfMem;
01022 newf0->index = yindex; newf0->ref = 1;
01023 cuddT(newf0) = f01;
01024 cuddE(newf0) = f10;
01025
01026
01027
01028 newykeys++;
01029 newf0->next = *previousP;
01030 *previousP = newf0;
01031 cuddSatInc(f01->ref);
01032 tmp = Cudd_Regular(f10);
01033 cuddSatInc(tmp->ref);
01034 }
01035 if (newcomplement) {
01036 newf0 = Cudd_Not(newf0);
01037 }
01038 }
01039 cuddE(f) = newf0;
01040
01041
01042
01043
01044
01045 posn = ddHash(newf1, newf0, xshift);
01046 newxkeys++;
01047 previousP = &(xlist[posn]);
01048 tmp = *previousP;
01049 while (newf1 < cuddT(tmp)) {
01050 previousP = &(tmp->next);
01051 tmp = *previousP;
01052 }
01053 while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
01054 previousP = &(tmp->next);
01055 tmp = *previousP;
01056 }
01057 f->next = *previousP;
01058 *previousP = f;
01059 f = next;
01060 }
01061
01062
01063
01064
01065 for (i = 0; i < yslots; i++) {
01066 previousP = &(ylist[i]);
01067 f = *previousP;
01068 while (f != sentinel) {
01069 next = f->next;
01070 if (f->ref == 0) {
01071 tmp = cuddT(f);
01072 cuddSatDec(tmp->ref);
01073 tmp = Cudd_Regular(cuddE(f));
01074 cuddSatDec(tmp->ref);
01075 cuddDeallocNode(table,f);
01076 newykeys--;
01077 } else {
01078 *previousP = f;
01079 previousP = &(f->next);
01080 }
01081 f = next;
01082 }
01083 *previousP = sentinel;
01084 }
01085
01086 #if DD_DEBUG
01087 #if 0
01088 (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y);
01089 #endif
01090 count = 0;
01091 idcheck = 0;
01092 for (i = 0; i < yslots; i++) {
01093 f = ylist[i];
01094 while (f != sentinel) {
01095 count++;
01096 if (f->index != (DdHalfWord) yindex)
01097 idcheck++;
01098 f = f->next;
01099 }
01100 }
01101 if (count != newykeys) {
01102 fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count);
01103 }
01104 if (idcheck != 0)
01105 fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck);
01106 count = 0;
01107 idcheck = 0;
01108 for (i = 0; i < xslots; i++) {
01109 f = xlist[i];
01110 while (f != sentinel) {
01111 count++;
01112 if (f->index != (DdHalfWord) xindex)
01113 idcheck++;
01114 f = f->next;
01115 }
01116 }
01117 if (count != newxkeys || newxkeys != oldxkeys) {
01118 fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count);
01119 }
01120 if (idcheck != 0)
01121 fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck);
01122 #endif
01123
01124 isolated += (table->vars[xindex]->ref == 1) +
01125 (table->vars[yindex]->ref == 1);
01126 table->isolated += isolated;
01127
01128
01129 table->subtables[y].keys = newykeys;
01130
01131
01132
01133
01134
01135
01136 table->keys += newykeys - oldykeys;
01137
01138 cuddXorLinear(table,xindex,yindex);
01139 }
01140
01141 #ifdef DD_DEBUG
01142 if (zero) {
01143 (void) Cudd_DebugCheck(table);
01144 }
01145 #endif
01146
01147 return(table->keys - table->isolated);
01148
01149 cuddLinearOutOfMem:
01150 (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n");
01151
01152 return (0);
01153
01154 }
01155
01156
01168 static void
01169 ddUpdateInteractionMatrix(
01170 DdManager * table,
01171 int xindex,
01172 int yindex)
01173 {
01174 int i;
01175 for (i = 0; i < yindex; i++) {
01176 if (i != xindex && cuddTestInteract(table,i,yindex)) {
01177 if (i < xindex) {
01178 cuddSetInteract(table,i,xindex);
01179 } else {
01180 cuddSetInteract(table,xindex,i);
01181 }
01182 }
01183 }
01184 for (i = yindex+1; i < table->size; i++) {
01185 if (i != xindex && cuddTestInteract(table,yindex,i)) {
01186 if (i < xindex) {
01187 cuddSetInteract(table,i,xindex);
01188 } else {
01189 cuddSetInteract(table,xindex,i);
01190 }
01191 }
01192 }
01193
01194 }
01195
01196
01208 static int
01209 cuddInitLinear(
01210 DdManager * table)
01211 {
01212 int words;
01213 int wordsPerRow;
01214 int nvars;
01215 int word;
01216 int bit;
01217 int i;
01218 long *linear;
01219
01220 nvars = table->size;
01221 wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
01222 words = wordsPerRow * nvars;
01223 table->linear = linear = ALLOC(long,words);
01224 if (linear == NULL) {
01225 table->errorCode = CUDD_MEMORY_OUT;
01226 return(0);
01227 }
01228 table->memused += words * sizeof(long);
01229 table->linearSize = nvars;
01230 for (i = 0; i < words; i++) linear[i] = 0;
01231 for (i = 0; i < nvars; i++) {
01232 word = wordsPerRow * i + (i >> LOGBPL);
01233 bit = i & (BPL-1);
01234 linear[word] = 1 << bit;
01235 }
01236 return(1);
01237
01238 }
01239
01240
01252 static int
01253 cuddResizeLinear(
01254 DdManager * table)
01255 {
01256 int words,oldWords;
01257 int wordsPerRow,oldWordsPerRow;
01258 int nvars,oldNvars;
01259 int word,oldWord;
01260 int bit;
01261 int i,j;
01262 long *linear,*oldLinear;
01263
01264 oldNvars = table->linearSize;
01265 oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1;
01266 oldWords = oldWordsPerRow * oldNvars;
01267 oldLinear = table->linear;
01268
01269 nvars = table->size;
01270 wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
01271 words = wordsPerRow * nvars;
01272 table->linear = linear = ALLOC(long,words);
01273 if (linear == NULL) {
01274 table->errorCode = CUDD_MEMORY_OUT;
01275 return(0);
01276 }
01277 table->memused += (words - oldWords) * sizeof(long);
01278 for (i = 0; i < words; i++) linear[i] = 0;
01279
01280
01281 for (i = 0; i < oldNvars; i++) {
01282 for (j = 0; j < oldWordsPerRow; j++) {
01283 oldWord = oldWordsPerRow * i + j;
01284 word = wordsPerRow * i + j;
01285 linear[word] = oldLinear[oldWord];
01286 }
01287 }
01288 FREE(oldLinear);
01289
01290
01291 for (i = oldNvars; i < nvars; i++) {
01292 word = wordsPerRow * i + (i >> LOGBPL);
01293 bit = i & (BPL-1);
01294 linear[word] = 1 << bit;
01295 }
01296 table->linearSize = nvars;
01297
01298 return(1);
01299
01300 }
01301
01302
01315 static void
01316 cuddXorLinear(
01317 DdManager * table,
01318 int x,
01319 int y)
01320 {
01321 int i;
01322 int nvars = table->size;
01323 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
01324 int xstart = wordsPerRow * x;
01325 int ystart = wordsPerRow * y;
01326 long *linear = table->linear;
01327
01328 for (i = 0; i < wordsPerRow; i++) {
01329 linear[xstart+i] ^= linear[ystart+i];
01330 }
01331
01332 }
01333