00001
00064 #include "util.h"
00065 #include "cuddInt.h"
00066
00067
00068
00069
00070
00071 #define CUDD_SWAP_MOVE 0
00072 #define CUDD_LINEAR_TRANSFORM_MOVE 1
00073 #define CUDD_INVERSE_TRANSFORM_MOVE 2
00074 #if SIZEOF_LONG == 8
00075 #define BPL 64
00076 #define LOGBPL 6
00077 #else
00078 #define BPL 32
00079 #define LOGBPL 5
00080 #endif
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 #ifndef lint
00095 static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.28 2009/02/19 16:21:03 fabio Exp $";
00096 #endif
00097
00098 static int *entry;
00099
00100 #ifdef DD_STATS
00101 extern int ddTotalNumberSwapping;
00102 extern int ddTotalNISwaps;
00103 static int ddTotalNumberLinearTr;
00104 #endif
00105
00106 #ifdef DD_DEBUG
00107 static int zero = 0;
00108 #endif
00109
00110
00111
00112
00113
00116
00117
00118
00119
00120 static int ddLinearUniqueCompare (int *ptrX, int *ptrY);
00121 static int ddLinearAndSiftingAux (DdManager *table, int x, int xLow, int xHigh);
00122 static Move * ddLinearAndSiftingUp (DdManager *table, int y, int xLow, Move *prevMoves);
00123 static Move * ddLinearAndSiftingDown (DdManager *table, int x, int xHigh, Move *prevMoves);
00124 static int ddLinearAndSiftingBackward (DdManager *table, int size, Move *moves);
00125 static Move* ddUndoMoves (DdManager *table, Move *moves);
00126 static void cuddXorLinear (DdManager *table, int x, int y);
00127
00131
00132
00133
00134
00135
00148 int
00149 Cudd_PrintLinear(
00150 DdManager * table)
00151 {
00152 int i,j,k;
00153 int retval;
00154 int nvars = table->linearSize;
00155 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00156 long word;
00157
00158 for (i = 0; i < nvars; i++) {
00159 for (j = 0; j < wordsPerRow; j++) {
00160 word = table->linear[i*wordsPerRow + j];
00161 for (k = 0; k < BPL; k++) {
00162 retval = fprintf(table->out,"%ld",word & 1);
00163 if (retval == 0) return(0);
00164 word >>= 1;
00165 }
00166 }
00167 retval = fprintf(table->out,"\n");
00168 if (retval == 0) return(0);
00169 }
00170 return(1);
00171
00172 }
00173
00174
00186 int
00187 Cudd_ReadLinear(
00188 DdManager * table ,
00189 int x ,
00190 int y )
00191 {
00192 int nvars = table->size;
00193 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00194 long word;
00195 int bit;
00196 int result;
00197
00198 assert(table->size == table->linearSize);
00199
00200 word = wordsPerRow * x + (y >> LOGBPL);
00201 bit = y & (BPL-1);
00202 result = (int) ((table->linear[word] >> bit) & 1);
00203 return(result);
00204
00205 }
00206
00207
00208
00209
00210
00211
00212
00235 int
00236 cuddLinearAndSifting(
00237 DdManager * table,
00238 int lower,
00239 int upper)
00240 {
00241 int i;
00242 int *var;
00243 int size;
00244 int x;
00245 int result;
00246 #ifdef DD_STATS
00247 int previousSize;
00248 #endif
00249
00250 #ifdef DD_STATS
00251 ddTotalNumberLinearTr = 0;
00252 #endif
00253
00254 size = table->size;
00255
00256 var = NULL;
00257 entry = NULL;
00258 if (table->linear == NULL) {
00259 result = cuddInitLinear(table);
00260 if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00261 #if 0
00262 (void) fprintf(table->out,"\n");
00263 result = Cudd_PrintLinear(table);
00264 if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00265 #endif
00266 } else if (table->size != table->linearSize) {
00267 result = cuddResizeLinear(table);
00268 if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00269 #if 0
00270 (void) fprintf(table->out,"\n");
00271 result = Cudd_PrintLinear(table);
00272 if (result == 0) goto cuddLinearAndSiftingOutOfMem;
00273 #endif
00274 }
00275
00276
00277 entry = ALLOC(int,size);
00278 if (entry == NULL) {
00279 table->errorCode = CUDD_MEMORY_OUT;
00280 goto cuddLinearAndSiftingOutOfMem;
00281 }
00282 var = ALLOC(int,size);
00283 if (var == NULL) {
00284 table->errorCode = CUDD_MEMORY_OUT;
00285 goto cuddLinearAndSiftingOutOfMem;
00286 }
00287
00288 for (i = 0; i < size; i++) {
00289 x = table->perm[i];
00290 entry[i] = table->subtables[x].keys;
00291 var[i] = i;
00292 }
00293
00294 qsort((void *)var,size,sizeof(int),(DD_QSFP)ddLinearUniqueCompare);
00295
00296
00297 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00298 x = table->perm[var[i]];
00299 if (x < lower || x > upper) continue;
00300 #ifdef DD_STATS
00301 previousSize = table->keys - table->isolated;
00302 #endif
00303 result = ddLinearAndSiftingAux(table,x,lower,upper);
00304 if (!result) goto cuddLinearAndSiftingOutOfMem;
00305 #ifdef DD_STATS
00306 if (table->keys < (unsigned) previousSize + table->isolated) {
00307 (void) fprintf(table->out,"-");
00308 } else if (table->keys > (unsigned) previousSize + table->isolated) {
00309 (void) fprintf(table->out,"+");
00310 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
00311 } else {
00312 (void) fprintf(table->out,"=");
00313 }
00314 fflush(table->out);
00315 #endif
00316 #ifdef DD_DEBUG
00317 (void) Cudd_DebugCheck(table);
00318 #endif
00319 }
00320
00321 FREE(var);
00322 FREE(entry);
00323
00324 #ifdef DD_STATS
00325 (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.",
00326 ddTotalNumberLinearTr);
00327 #endif
00328
00329 return(1);
00330
00331 cuddLinearAndSiftingOutOfMem:
00332
00333 if (entry != NULL) FREE(entry);
00334 if (var != NULL) FREE(var);
00335
00336 return(0);
00337
00338 }
00339
00340
00359 int
00360 cuddLinearInPlace(
00361 DdManager * table,
00362 int x,
00363 int y)
00364 {
00365 DdNodePtr *xlist, *ylist;
00366 int xindex, yindex;
00367 int xslots, yslots;
00368 int xshift, yshift;
00369 int oldxkeys, oldykeys;
00370 int newxkeys, newykeys;
00371 int comple, newcomplement;
00372 int i;
00373 int posn;
00374 int isolated;
00375 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
00376 DdNode *g,*next,*last;
00377 DdNodePtr *previousP;
00378 DdNode *tmp;
00379 DdNode *sentinel = &(table->sentinel);
00380 #ifdef DD_DEBUG
00381 int count, idcheck;
00382 #endif
00383
00384 #ifdef DD_DEBUG
00385 assert(x < y);
00386 assert(cuddNextHigh(table,x) == y);
00387 assert(table->subtables[x].keys != 0);
00388 assert(table->subtables[y].keys != 0);
00389 assert(table->subtables[x].dead == 0);
00390 assert(table->subtables[y].dead == 0);
00391 #endif
00392
00393 xindex = table->invperm[x];
00394 yindex = table->invperm[y];
00395
00396 if (cuddTestInteract(table,xindex,yindex)) {
00397 #ifdef DD_STATS
00398 ddTotalNumberLinearTr++;
00399 #endif
00400
00401 xlist = table->subtables[x].nodelist;
00402 oldxkeys = table->subtables[x].keys;
00403 xslots = table->subtables[x].slots;
00404 xshift = table->subtables[x].shift;
00405
00406
00407 ylist = table->subtables[y].nodelist;
00408 oldykeys = table->subtables[y].keys;
00409 yslots = table->subtables[y].slots;
00410 yshift = table->subtables[y].shift;
00411
00412 newxkeys = 0;
00413 newykeys = oldykeys;
00414
00415
00416
00417
00418
00419
00420
00421 isolated = - ((table->vars[xindex]->ref == 1) +
00422 (table->vars[yindex]->ref == 1));
00423
00424
00425
00426
00427
00428 g = NULL;
00429 #ifdef DD_DEBUG
00430 last = NULL;
00431 #endif
00432 for (i = 0; i < xslots; i++) {
00433 f = xlist[i];
00434 if (f == sentinel) continue;
00435 xlist[i] = sentinel;
00436 if (g == NULL) {
00437 g = f;
00438 } else {
00439 last->next = f;
00440 }
00441 while ((next = f->next) != sentinel) {
00442 f = next;
00443 }
00444 last = f;
00445 }
00446 #ifdef DD_DEBUG
00447
00448
00449 assert(last != NULL);
00450 #endif
00451 last->next = NULL;
00452
00453 #ifdef DD_COUNT
00454 table->swapSteps += oldxkeys;
00455 #endif
00456
00457
00458
00459 f = g;
00460 while (f != NULL) {
00461 next = f->next;
00462
00463 f1 = cuddT(f);
00464 #ifdef DD_DEBUG
00465 assert(!(Cudd_IsComplement(f1)));
00466 #endif
00467 if ((int) f1->index == yindex) {
00468 f11 = cuddT(f1); f10 = cuddE(f1);
00469 } else {
00470 f11 = f10 = f1;
00471 }
00472 #ifdef DD_DEBUG
00473 assert(!(Cudd_IsComplement(f11)));
00474 #endif
00475 f0 = cuddE(f);
00476 comple = Cudd_IsComplement(f0);
00477 f0 = Cudd_Regular(f0);
00478 if ((int) f0->index == yindex) {
00479 f01 = cuddT(f0); f00 = cuddE(f0);
00480 } else {
00481 f01 = f00 = f0;
00482 }
00483 if (comple) {
00484 f01 = Cudd_Not(f01);
00485 f00 = Cudd_Not(f00);
00486 }
00487
00488 cuddSatDec(f1->ref);
00489
00490 if (f11 == f00) {
00491 newf1 = f11;
00492 cuddSatInc(newf1->ref);
00493 } else {
00494
00495 posn = ddHash(f11, f00, yshift);
00496
00497 previousP = &(ylist[posn]);
00498 newf1 = *previousP;
00499 while (f11 < cuddT(newf1)) {
00500 previousP = &(newf1->next);
00501 newf1 = *previousP;
00502 }
00503 while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) {
00504 previousP = &(newf1->next);
00505 newf1 = *previousP;
00506 }
00507 if (cuddT(newf1) == f11 && cuddE(newf1) == f00) {
00508 cuddSatInc(newf1->ref);
00509 } else {
00510 newf1 = cuddDynamicAllocNode(table);
00511 if (newf1 == NULL)
00512 goto cuddLinearOutOfMem;
00513 newf1->index = yindex; newf1->ref = 1;
00514 cuddT(newf1) = f11;
00515 cuddE(newf1) = f00;
00516
00517
00518
00519 newykeys++;
00520 newf1->next = *previousP;
00521 *previousP = newf1;
00522 cuddSatInc(f11->ref);
00523 tmp = Cudd_Regular(f00);
00524 cuddSatInc(tmp->ref);
00525 }
00526 }
00527 cuddT(f) = newf1;
00528 #ifdef DD_DEBUG
00529 assert(!(Cudd_IsComplement(newf1)));
00530 #endif
00531
00532
00533
00534 tmp = Cudd_Regular(f0);
00535 cuddSatDec(tmp->ref);
00536
00537 if (f01 == f10) {
00538 newf0 = f01;
00539 tmp = Cudd_Regular(newf0);
00540 cuddSatInc(tmp->ref);
00541 } else {
00542
00543 newcomplement = Cudd_IsComplement(f01);
00544 if (newcomplement) {
00545 f01 = Cudd_Not(f01);
00546 f10 = Cudd_Not(f10);
00547 }
00548
00549 posn = ddHash(f01, f10, yshift);
00550
00551 previousP = &(ylist[posn]);
00552 newf0 = *previousP;
00553 while (f01 < cuddT(newf0)) {
00554 previousP = &(newf0->next);
00555 newf0 = *previousP;
00556 }
00557 while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) {
00558 previousP = &(newf0->next);
00559 newf0 = *previousP;
00560 }
00561 if (cuddT(newf0) == f01 && cuddE(newf0) == f10) {
00562 cuddSatInc(newf0->ref);
00563 } else {
00564 newf0 = cuddDynamicAllocNode(table);
00565 if (newf0 == NULL)
00566 goto cuddLinearOutOfMem;
00567 newf0->index = yindex; newf0->ref = 1;
00568 cuddT(newf0) = f01;
00569 cuddE(newf0) = f10;
00570
00571
00572
00573 newykeys++;
00574 newf0->next = *previousP;
00575 *previousP = newf0;
00576 cuddSatInc(f01->ref);
00577 tmp = Cudd_Regular(f10);
00578 cuddSatInc(tmp->ref);
00579 }
00580 if (newcomplement) {
00581 newf0 = Cudd_Not(newf0);
00582 }
00583 }
00584 cuddE(f) = newf0;
00585
00586
00587
00588
00589
00590 posn = ddHash(newf1, newf0, xshift);
00591 newxkeys++;
00592 previousP = &(xlist[posn]);
00593 tmp = *previousP;
00594 while (newf1 < cuddT(tmp)) {
00595 previousP = &(tmp->next);
00596 tmp = *previousP;
00597 }
00598 while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
00599 previousP = &(tmp->next);
00600 tmp = *previousP;
00601 }
00602 f->next = *previousP;
00603 *previousP = f;
00604 f = next;
00605 }
00606
00607
00608
00609
00610 for (i = 0; i < yslots; i++) {
00611 previousP = &(ylist[i]);
00612 f = *previousP;
00613 while (f != sentinel) {
00614 next = f->next;
00615 if (f->ref == 0) {
00616 tmp = cuddT(f);
00617 cuddSatDec(tmp->ref);
00618 tmp = Cudd_Regular(cuddE(f));
00619 cuddSatDec(tmp->ref);
00620 cuddDeallocNode(table,f);
00621 newykeys--;
00622 } else {
00623 *previousP = f;
00624 previousP = &(f->next);
00625 }
00626 f = next;
00627 }
00628 *previousP = sentinel;
00629 }
00630
00631 #ifdef DD_DEBUG
00632 #if 0
00633 (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y);
00634 #endif
00635 count = 0;
00636 idcheck = 0;
00637 for (i = 0; i < yslots; i++) {
00638 f = ylist[i];
00639 while (f != sentinel) {
00640 count++;
00641 if (f->index != (DdHalfWord) yindex)
00642 idcheck++;
00643 f = f->next;
00644 }
00645 }
00646 if (count != newykeys) {
00647 fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count);
00648 }
00649 if (idcheck != 0)
00650 fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck);
00651 count = 0;
00652 idcheck = 0;
00653 for (i = 0; i < xslots; i++) {
00654 f = xlist[i];
00655 while (f != sentinel) {
00656 count++;
00657 if (f->index != (DdHalfWord) xindex)
00658 idcheck++;
00659 f = f->next;
00660 }
00661 }
00662 if (count != newxkeys || newxkeys != oldxkeys) {
00663 fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count);
00664 }
00665 if (idcheck != 0)
00666 fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck);
00667 #endif
00668
00669 isolated += (table->vars[xindex]->ref == 1) +
00670 (table->vars[yindex]->ref == 1);
00671 table->isolated += isolated;
00672
00673
00674 table->subtables[y].keys = newykeys;
00675
00676
00677
00678
00679
00680
00681 table->keys += newykeys - oldykeys;
00682
00683 cuddXorLinear(table,xindex,yindex);
00684 }
00685
00686 #ifdef DD_DEBUG
00687 if (zero) {
00688 (void) Cudd_DebugCheck(table);
00689 }
00690 #endif
00691
00692 return(table->keys - table->isolated);
00693
00694 cuddLinearOutOfMem:
00695 (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n");
00696
00697 return (0);
00698
00699 }
00700
00701
00713 void
00714 cuddUpdateInteractionMatrix(
00715 DdManager * table,
00716 int xindex,
00717 int yindex)
00718 {
00719 int i;
00720 for (i = 0; i < yindex; i++) {
00721 if (i != xindex && cuddTestInteract(table,i,yindex)) {
00722 if (i < xindex) {
00723 cuddSetInteract(table,i,xindex);
00724 } else {
00725 cuddSetInteract(table,xindex,i);
00726 }
00727 }
00728 }
00729 for (i = yindex+1; i < table->size; i++) {
00730 if (i != xindex && cuddTestInteract(table,yindex,i)) {
00731 if (i < xindex) {
00732 cuddSetInteract(table,i,xindex);
00733 } else {
00734 cuddSetInteract(table,xindex,i);
00735 }
00736 }
00737 }
00738
00739 }
00740
00741
00754 int
00755 cuddInitLinear(
00756 DdManager * table)
00757 {
00758 int words;
00759 int wordsPerRow;
00760 int nvars;
00761 int word;
00762 int bit;
00763 int i;
00764 long *linear;
00765
00766 nvars = table->size;
00767 wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00768 words = wordsPerRow * nvars;
00769 table->linear = linear = ALLOC(long,words);
00770 if (linear == NULL) {
00771 table->errorCode = CUDD_MEMORY_OUT;
00772 return(0);
00773 }
00774 table->memused += words * sizeof(long);
00775 table->linearSize = nvars;
00776 for (i = 0; i < words; i++) linear[i] = 0;
00777 for (i = 0; i < nvars; i++) {
00778 word = wordsPerRow * i + (i >> LOGBPL);
00779 bit = i & (BPL-1);
00780 linear[word] = 1 << bit;
00781 }
00782 return(1);
00783
00784 }
00785
00786
00799 int
00800 cuddResizeLinear(
00801 DdManager * table)
00802 {
00803 int words,oldWords;
00804 int wordsPerRow,oldWordsPerRow;
00805 int nvars,oldNvars;
00806 int word,oldWord;
00807 int bit;
00808 int i,j;
00809 long *linear,*oldLinear;
00810
00811 oldNvars = table->linearSize;
00812 oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1;
00813 oldWords = oldWordsPerRow * oldNvars;
00814 oldLinear = table->linear;
00815
00816 nvars = table->size;
00817 wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
00818 words = wordsPerRow * nvars;
00819 table->linear = linear = ALLOC(long,words);
00820 if (linear == NULL) {
00821 table->errorCode = CUDD_MEMORY_OUT;
00822 return(0);
00823 }
00824 table->memused += (words - oldWords) * sizeof(long);
00825 for (i = 0; i < words; i++) linear[i] = 0;
00826
00827
00828 for (i = 0; i < oldNvars; i++) {
00829 for (j = 0; j < oldWordsPerRow; j++) {
00830 oldWord = oldWordsPerRow * i + j;
00831 word = wordsPerRow * i + j;
00832 linear[word] = oldLinear[oldWord];
00833 }
00834 }
00835 FREE(oldLinear);
00836
00837
00838 for (i = oldNvars; i < nvars; i++) {
00839 word = wordsPerRow * i + (i >> LOGBPL);
00840 bit = i & (BPL-1);
00841 linear[word] = 1 << bit;
00842 }
00843 table->linearSize = nvars;
00844
00845 return(1);
00846
00847 }
00848
00849
00850
00851
00852
00853
00854
00867 static int
00868 ddLinearUniqueCompare(
00869 int * ptrX,
00870 int * ptrY)
00871 {
00872 #if 0
00873 if (entry[*ptrY] == entry[*ptrX]) {
00874 return((*ptrX) - (*ptrY));
00875 }
00876 #endif
00877 return(entry[*ptrY] - entry[*ptrX]);
00878
00879 }
00880
00881
00895 static int
00896 ddLinearAndSiftingAux(
00897 DdManager * table,
00898 int x,
00899 int xLow,
00900 int xHigh)
00901 {
00902
00903 Move *move;
00904 Move *moveUp;
00905 Move *moveDown;
00906 int initialSize;
00907 int result;
00908
00909 initialSize = table->keys - table->isolated;
00910
00911 moveDown = NULL;
00912 moveUp = NULL;
00913
00914 if (x == xLow) {
00915 moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
00916
00917 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00918
00919 result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
00920 if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00921
00922 } else if (x == xHigh) {
00923 moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
00924
00925 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00926
00927 result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
00928 if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00929
00930 } else if ((x - xLow) > (xHigh - x)) {
00931 moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL);
00932
00933 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00934 moveUp = ddUndoMoves(table,moveDown);
00935 #ifdef DD_DEBUG
00936 assert(moveUp == NULL || moveUp->x == x);
00937 #endif
00938 moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp);
00939 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00940
00941 result = ddLinearAndSiftingBackward(table,initialSize,moveUp);
00942 if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00943
00944 } else {
00945 moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL);
00946
00947 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00948 moveDown = ddUndoMoves(table,moveUp);
00949 #ifdef DD_DEBUG
00950 assert(moveDown == NULL || moveDown->y == x);
00951 #endif
00952 moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown);
00953 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem;
00954
00955 result = ddLinearAndSiftingBackward(table,initialSize,moveDown);
00956 if (!result) goto ddLinearAndSiftingAuxOutOfMem;
00957 }
00958
00959 while (moveDown != NULL) {
00960 move = moveDown->next;
00961 cuddDeallocMove(table, moveDown);
00962 moveDown = move;
00963 }
00964 while (moveUp != NULL) {
00965 move = moveUp->next;
00966 cuddDeallocMove(table, moveUp);
00967 moveUp = move;
00968 }
00969
00970 return(1);
00971
00972 ddLinearAndSiftingAuxOutOfMem:
00973 while (moveDown != NULL) {
00974 move = moveDown->next;
00975 cuddDeallocMove(table, moveDown);
00976 moveDown = move;
00977 }
00978 while (moveUp != NULL) {
00979 move = moveUp->next;
00980 cuddDeallocMove(table, moveUp);
00981 moveUp = move;
00982 }
00983
00984 return(0);
00985
00986 }
00987
00988
01001 static Move *
01002 ddLinearAndSiftingUp(
01003 DdManager * table,
01004 int y,
01005 int xLow,
01006 Move * prevMoves)
01007 {
01008 Move *moves;
01009 Move *move;
01010 int x;
01011 int size, newsize;
01012 int limitSize;
01013 int xindex, yindex;
01014 int isolated;
01015 int L;
01016 #ifdef DD_DEBUG
01017 int checkL;
01018 int z;
01019 int zindex;
01020 #endif
01021
01022 moves = prevMoves;
01023 yindex = table->invperm[y];
01024
01025
01026
01027
01028
01029
01030
01031 limitSize = L = table->keys - table->isolated;
01032 for (x = xLow + 1; x < y; x++) {
01033 xindex = table->invperm[x];
01034 if (cuddTestInteract(table,xindex,yindex)) {
01035 isolated = table->vars[xindex]->ref == 1;
01036 L -= table->subtables[x].keys - isolated;
01037 }
01038 }
01039 isolated = table->vars[yindex]->ref == 1;
01040 L -= table->subtables[y].keys - isolated;
01041
01042 x = cuddNextLow(table,y);
01043 while (x >= xLow && L <= limitSize) {
01044 xindex = table->invperm[x];
01045 #ifdef DD_DEBUG
01046 checkL = table->keys - table->isolated;
01047 for (z = xLow + 1; z < y; z++) {
01048 zindex = table->invperm[z];
01049 if (cuddTestInteract(table,zindex,yindex)) {
01050 isolated = table->vars[zindex]->ref == 1;
01051 checkL -= table->subtables[z].keys - isolated;
01052 }
01053 }
01054 isolated = table->vars[yindex]->ref == 1;
01055 checkL -= table->subtables[y].keys - isolated;
01056 if (L != checkL) {
01057 (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L);
01058 }
01059 #endif
01060 size = cuddSwapInPlace(table,x,y);
01061 if (size == 0) goto ddLinearAndSiftingUpOutOfMem;
01062 newsize = cuddLinearInPlace(table,x,y);
01063 if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
01064 move = (Move *) cuddDynamicAllocNode(table);
01065 if (move == NULL) goto ddLinearAndSiftingUpOutOfMem;
01066 move->x = x;
01067 move->y = y;
01068 move->next = moves;
01069 moves = move;
01070 move->flags = CUDD_SWAP_MOVE;
01071 if (newsize >= size) {
01072
01073
01074
01075
01076 newsize = cuddLinearInPlace(table,x,y);
01077 if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem;
01078 #ifdef DD_DEBUG
01079 if (newsize != size) {
01080 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
01081 }
01082 #endif
01083 } else if (cuddTestInteract(table,xindex,yindex)) {
01084 size = newsize;
01085 move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
01086 cuddUpdateInteractionMatrix(table,xindex,yindex);
01087 }
01088 move->size = size;
01089
01090 if (cuddTestInteract(table,xindex,yindex)) {
01091 isolated = table->vars[xindex]->ref == 1;
01092 L += table->subtables[y].keys - isolated;
01093 }
01094 if ((double) size > (double) limitSize * table->maxGrowth) break;
01095 if (size < limitSize) limitSize = size;
01096 y = x;
01097 x = cuddNextLow(table,y);
01098 }
01099 return(moves);
01100
01101 ddLinearAndSiftingUpOutOfMem:
01102 while (moves != NULL) {
01103 move = moves->next;
01104 cuddDeallocMove(table, moves);
01105 moves = move;
01106 }
01107 return((Move *) CUDD_OUT_OF_MEM);
01108
01109 }
01110
01111
01124 static Move *
01125 ddLinearAndSiftingDown(
01126 DdManager * table,
01127 int x,
01128 int xHigh,
01129 Move * prevMoves)
01130 {
01131 Move *moves;
01132 Move *move;
01133 int y;
01134 int size, newsize;
01135 int R;
01136 int limitSize;
01137 int xindex, yindex;
01138 int isolated;
01139 #ifdef DD_DEBUG
01140 int checkR;
01141 int z;
01142 int zindex;
01143 #endif
01144
01145 moves = prevMoves;
01146
01147 xindex = table->invperm[x];
01148 limitSize = size = table->keys - table->isolated;
01149 R = 0;
01150 for (y = xHigh; y > x; y--) {
01151 yindex = table->invperm[y];
01152 if (cuddTestInteract(table,xindex,yindex)) {
01153 isolated = table->vars[yindex]->ref == 1;
01154 R += table->subtables[y].keys - isolated;
01155 }
01156 }
01157
01158 y = cuddNextHigh(table,x);
01159 while (y <= xHigh && size - R < limitSize) {
01160 #ifdef DD_DEBUG
01161 checkR = 0;
01162 for (z = xHigh; z > x; z--) {
01163 zindex = table->invperm[z];
01164 if (cuddTestInteract(table,xindex,zindex)) {
01165 isolated = table->vars[zindex]->ref == 1;
01166 checkR += table->subtables[z].keys - isolated;
01167 }
01168 }
01169 if (R != checkR) {
01170 (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R);
01171 }
01172 #endif
01173
01174 yindex = table->invperm[y];
01175 if (cuddTestInteract(table,xindex,yindex)) {
01176 isolated = table->vars[yindex]->ref == 1;
01177 R -= table->subtables[y].keys - isolated;
01178 }
01179 size = cuddSwapInPlace(table,x,y);
01180 if (size == 0) goto ddLinearAndSiftingDownOutOfMem;
01181 newsize = cuddLinearInPlace(table,x,y);
01182 if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
01183 move = (Move *) cuddDynamicAllocNode(table);
01184 if (move == NULL) goto ddLinearAndSiftingDownOutOfMem;
01185 move->x = x;
01186 move->y = y;
01187 move->next = moves;
01188 moves = move;
01189 move->flags = CUDD_SWAP_MOVE;
01190 if (newsize >= size) {
01191
01192
01193
01194
01195 newsize = cuddLinearInPlace(table,x,y);
01196 if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem;
01197 if (newsize != size) {
01198 (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize);
01199 }
01200 } else if (cuddTestInteract(table,xindex,yindex)) {
01201 size = newsize;
01202 move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
01203 cuddUpdateInteractionMatrix(table,xindex,yindex);
01204 }
01205 move->size = size;
01206 if ((double) size > (double) limitSize * table->maxGrowth) break;
01207 if (size < limitSize) limitSize = size;
01208 x = y;
01209 y = cuddNextHigh(table,x);
01210 }
01211 return(moves);
01212
01213 ddLinearAndSiftingDownOutOfMem:
01214 while (moves != NULL) {
01215 move = moves->next;
01216 cuddDeallocMove(table, moves);
01217 moves = move;
01218 }
01219 return((Move *) CUDD_OUT_OF_MEM);
01220
01221 }
01222
01223
01237 static int
01238 ddLinearAndSiftingBackward(
01239 DdManager * table,
01240 int size,
01241 Move * moves)
01242 {
01243 Move *move;
01244 int res;
01245
01246 for (move = moves; move != NULL; move = move->next) {
01247 if (move->size < size) {
01248 size = move->size;
01249 }
01250 }
01251
01252 for (move = moves; move != NULL; move = move->next) {
01253 if (move->size == size) return(1);
01254 if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
01255 res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
01256 if (!res) return(0);
01257 }
01258 res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01259 if (!res) return(0);
01260 if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) {
01261 res = cuddLinearInPlace(table,(int)move->x,(int)move->y);
01262 if (!res) return(0);
01263 }
01264 }
01265
01266 return(1);
01267
01268 }
01269
01270
01283 static Move*
01284 ddUndoMoves(
01285 DdManager * table,
01286 Move * moves)
01287 {
01288 Move *invmoves = NULL;
01289 Move *move;
01290 Move *invmove;
01291 int size;
01292
01293 for (move = moves; move != NULL; move = move->next) {
01294 invmove = (Move *) cuddDynamicAllocNode(table);
01295 if (invmove == NULL) goto ddUndoMovesOutOfMem;
01296 invmove->x = move->x;
01297 invmove->y = move->y;
01298 invmove->next = invmoves;
01299 invmoves = invmove;
01300 if (move->flags == CUDD_SWAP_MOVE) {
01301 invmove->flags = CUDD_SWAP_MOVE;
01302 size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01303 if (!size) goto ddUndoMovesOutOfMem;
01304 } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) {
01305 invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE;
01306 size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
01307 if (!size) goto ddUndoMovesOutOfMem;
01308 size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01309 if (!size) goto ddUndoMovesOutOfMem;
01310 } else {
01311 #ifdef DD_DEBUG
01312 (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n");
01313 #endif
01314 invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE;
01315 size = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01316 if (!size) goto ddUndoMovesOutOfMem;
01317 size = cuddLinearInPlace(table,(int)move->x,(int)move->y);
01318 if (!size) goto ddUndoMovesOutOfMem;
01319 }
01320 invmove->size = size;
01321 }
01322
01323 return(invmoves);
01324
01325 ddUndoMovesOutOfMem:
01326 while (invmoves != NULL) {
01327 move = invmoves->next;
01328 cuddDeallocMove(table, invmoves);
01329 invmoves = move;
01330 }
01331 return((Move *) CUDD_OUT_OF_MEM);
01332
01333 }
01334
01335
01348 static void
01349 cuddXorLinear(
01350 DdManager * table,
01351 int x,
01352 int y)
01353 {
01354 int i;
01355 int nvars = table->size;
01356 int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1;
01357 int xstart = wordsPerRow * x;
01358 int ystart = wordsPerRow * y;
01359 long *linear = table->linear;
01360
01361 for (i = 0; i < wordsPerRow; i++) {
01362 linear[xstart+i] ^= linear[ystart+i];
01363 }
01364
01365 }