cuddBddIte.c 36.5 KB
Newer Older
Alan Mishchenko committed
1 2 3 4 5 6 7 8 9
/**CFile***********************************************************************

  FileName    [cuddBddIte.c]

  PackageName [cudd]

  Synopsis    [BDD ITE function and satellites.]

  Description [External procedures included in this module:
10
                <ul>
Alan Mishchenko committed
11
                <li> Cudd_bddIte()
12 13 14 15 16 17 18 19 20 21 22
                <li> Cudd_bddIteConstant()
                <li> Cudd_bddIntersect()
                <li> Cudd_bddAnd()
                <li> Cudd_bddAndLimit()
                <li> Cudd_bddOr()
                <li> Cudd_bddNand()
                <li> Cudd_bddNor()
                <li> Cudd_bddXor()
                <li> Cudd_bddXnor()
                <li> Cudd_bddLeq()
                </ul>
Alan Mishchenko committed
23
       Internal procedures included in this module:
24 25 26 27 28 29
                <ul>
                <li> cuddBddIteRecur()
                <li> cuddBddIntersectRecur()
                <li> cuddBddAndRecur()
                <li> cuddBddXorRecur()
                </ul>
Alan Mishchenko committed
30
       Static procedures included in this module:
31 32 33 34 35
                <ul>
                <li> bddVarToConst()
                <li> bddVarToCanonical()
                <li> bddVarToCanonicalSimple()
                </ul>]
Alan Mishchenko committed
36 37 38 39 40

  SeeAlso     []

  Author      [Fabio Somenzi]

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
  Copyright   [Copyright (c) 1995-2004, 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.]
Alan Mishchenko committed
72 73 74

******************************************************************************/

75
#include "misc/util/util_hack.h"
Alan Mishchenko committed
76 77
#include "cuddInt.h"

78 79 80
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
81

82

Alan Mishchenko committed
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
/*---------------------------------------------------------------------------*/
/* Constant declarations                                                     */
/*---------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------*/
/* Stucture declarations                                                     */
/*---------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------*/
/* Type declarations                                                         */
/*---------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------*/
/* Variable declarations                                                     */
/*---------------------------------------------------------------------------*/

#ifndef lint
103
static char rcsid[] DD_UNUSED = "$Id: cuddBddIte.c,v 1.24 2004/08/13 18:04:46 fabio Exp $";
Alan Mishchenko committed
104 105 106 107 108 109 110 111 112 113 114 115 116
#endif

/*---------------------------------------------------------------------------*/
/* Macro declarations                                                        */
/*---------------------------------------------------------------------------*/


/**AutomaticStart*************************************************************/

/*---------------------------------------------------------------------------*/
/* Static function prototypes                                                */
/*---------------------------------------------------------------------------*/

117 118 119
static void bddVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one);
static int bddVarToCanonical (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp);
static int bddVarToCanonicalSimple (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp);
Alan Mishchenko committed
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

/**AutomaticEnd***************************************************************/


/*---------------------------------------------------------------------------*/
/* Definition of exported functions                                          */
/*---------------------------------------------------------------------------*/


/**Function********************************************************************

  Synopsis    [Implements ITE(f,g,h).]

  Description [Implements ITE(f,g,h). Returns a pointer to the
  resulting BDD if successful; NULL if the intermediate result blows
  up.]

  SideEffects [None]

  SeeAlso     [Cudd_addIte Cudd_bddIteConstant Cudd_bddIntersect]

******************************************************************************/
DdNode *
Cudd_bddIte(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  DdNode * h)
{
    DdNode *res;

    do {
152 153
        dd->reordered = 0;
        res = cuddBddIteRecur(dd,f,g,h);
Alan Mishchenko committed
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    } while (dd->reordered == 1);
    return(res);

} /* end of Cudd_bddIte */


/**Function********************************************************************

  Synopsis    [Implements ITEconstant(f,g,h).]

  Description [Implements ITEconstant(f,g,h). Returns a pointer to the
  resulting BDD (which may or may not be constant) or DD_NON_CONSTANT.
  No new nodes are created.]

  SideEffects [None]

  SeeAlso     [Cudd_bddIte Cudd_bddIntersect Cudd_bddLeq Cudd_addIteConstant]

******************************************************************************/
DdNode *
Cudd_bddIteConstant(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  DdNode * h)
{
180 181 182 183
    DdNode       *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
    DdNode       *one = DD_ONE(dd);
    DdNode       *zero = Cudd_Not(one);
    int          comple;
Alan Mishchenko committed
184 185 186 187
    unsigned int topf, topg, toph, v;

    statLine(dd);
    /* Trivial cases. */
188 189
    if (f == one)                       /* ITE(1,G,H) => G */
        return(g);
Alan Mishchenko committed
190
    
191 192
    if (f == zero)                      /* ITE(0,G,H) => H */
        return(h);
Alan Mishchenko committed
193 194
    
    /* f now not a constant. */
195 196
    bddVarToConst(f, &g, &h, one);      /* possibly convert g or h */
                                        /* to constants */
Alan Mishchenko committed
197

198 199
    if (g == h)                         /* ITE(F,G,G) => G */
        return(g);
Alan Mishchenko committed
200 201

    if (Cudd_IsConstant(g) && Cudd_IsConstant(h)) 
202 203
        return(DD_NON_CONSTANT);        /* ITE(F,1,0) or ITE(F,0,1) */
                                        /* => DD_NON_CONSTANT */
Alan Mishchenko committed
204 205
    
    if (g == Cudd_Not(h))
206 207
        return(DD_NON_CONSTANT);        /* ITE(F,G,G') => DD_NON_CONSTANT */
                                        /* if F != G and F != G' */
Alan Mishchenko committed
208 209 210 211 212 213
    
    comple = bddVarToCanonical(dd, &f, &g, &h, &topf, &topg, &toph);

    /* Cache lookup. */
    r = cuddConstantLookup(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h);
    if (r != NULL) {
214
        return(Cudd_NotCond(r,comple && r != DD_NON_CONSTANT));
Alan Mishchenko committed
215 216 217 218 219 220
    }

    v = ddMin(topg, toph);

    /* ITE(F,G,H) = (v,G,H) (non constant) if F = (v,1,0), v < top(G,H). */
    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
221
        return(DD_NON_CONSTANT);
Alan Mishchenko committed
222 223 224 225
    }

    /* Compute cofactors. */
    if (topf <= v) {
226 227
        v = ddMin(topf, v);             /* v = top_var(F,G,H) */
        Fv = cuddT(f); Fnv = cuddE(f);
Alan Mishchenko committed
228
    } else {
229
        Fv = Fnv = f;
Alan Mishchenko committed
230 231 232
    }

    if (topg == v) {
233
        Gv = cuddT(g); Gnv = cuddE(g);
Alan Mishchenko committed
234
    } else {
235
        Gv = Gnv = g;
Alan Mishchenko committed
236 237 238
    }

    if (toph == v) {
239 240 241 242 243 244
        H = Cudd_Regular(h);
        Hv = cuddT(H); Hnv = cuddE(H);
        if (Cudd_IsComplement(h)) {
            Hv = Cudd_Not(Hv);
            Hnv = Cudd_Not(Hnv);
        }
Alan Mishchenko committed
245
    } else {
246
        Hv = Hnv = h;
Alan Mishchenko committed
247 248 249 250 251
    }

    /* Recursion. */
    t = Cudd_bddIteConstant(dd, Fv, Gv, Hv);
    if (t == DD_NON_CONSTANT || !Cudd_IsConstant(t)) {
252 253
        cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
        return(DD_NON_CONSTANT);
Alan Mishchenko committed
254 255 256
    }
    e = Cudd_bddIteConstant(dd, Fnv, Gnv, Hnv);
    if (e == DD_NON_CONSTANT || !Cudd_IsConstant(e) || t != e) {
257 258
        cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
        return(DD_NON_CONSTANT);
Alan Mishchenko committed
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
    }
    cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, t);
    return(Cudd_NotCond(t,comple));

} /* end of Cudd_bddIteConstant */


/**Function********************************************************************

  Synopsis    [Returns a function included in the intersection of f and g.]

  Description [Computes a function included in the intersection of f and
  g. (That is, a witness that the intersection is not empty.)
  Cudd_bddIntersect tries to build as few new nodes as possible. If the
  only result of interest is whether f and g intersect,
  Cudd_bddLeq should be used instead.]

  SideEffects [None]

  SeeAlso     [Cudd_bddLeq Cudd_bddIteConstant]

******************************************************************************/
DdNode *
Cudd_bddIntersect(
  DdManager * dd /* manager */,
  DdNode * f /* first operand */,
  DdNode * g /* second operand */)
{
    DdNode *res;

    do {
290 291
        dd->reordered = 0;
        res = cuddBddIntersectRecur(dd,f,g);
Alan Mishchenko committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
    } while (dd->reordered == 1);

    return(res);

} /* end of Cudd_bddIntersect */


/**Function********************************************************************

  Synopsis    [Computes the conjunction of two BDDs f and g.]

  Description [Computes the conjunction of two BDDs f and g. Returns a
  pointer to the resulting BDD if successful; NULL if the intermediate
  result blows up.]

  SideEffects [None]

  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect
  Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor]

******************************************************************************/
DdNode *
Cudd_bddAnd(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    DdNode *res;

    do {
322 323
        dd->reordered = 0;
        res = cuddBddAndRecur(dd,f,g);
Alan Mishchenko committed
324 325 326 327 328 329 330 331
    } while (dd->reordered == 1);
    return(res);

} /* end of Cudd_bddAnd */


/**Function********************************************************************

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
  Synopsis    [Computes the conjunction of two BDDs f and g.  Returns
  NULL if too many nodes are required.]

  Description [Computes the conjunction of two BDDs f and g. Returns a
  pointer to the resulting BDD if successful; NULL if the intermediate
  result blows up or more new nodes than <code>limit</code> are
  required.]

  SideEffects [None]

  SeeAlso     [Cudd_bddAnd]

******************************************************************************/
DdNode *
Cudd_bddAndLimit(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  unsigned int limit)
{
    DdNode *res;
    unsigned int saveLimit = dd->maxLive;

    dd->maxLive = (dd->keys - dd->dead) + (dd->keysZ - dd->deadZ) + limit;
    do {
        dd->reordered = 0;
        res = cuddBddAndRecur(dd,f,g);
    } while (dd->reordered == 1);
    dd->maxLive = saveLimit;
    return(res);

} /* end of Cudd_bddAndLimit */


/**Function********************************************************************

Alan Mishchenko committed
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
  Synopsis    [Computes the disjunction of two BDDs f and g.]

  Description [Computes the disjunction of two BDDs f and g. Returns a
  pointer to the resulting BDD if successful; NULL if the intermediate
  result blows up.]

  SideEffects [None]

  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddNand Cudd_bddNor
  Cudd_bddXor Cudd_bddXnor]

******************************************************************************/
DdNode *
Cudd_bddOr(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    DdNode *res;

    do {
389 390
        dd->reordered = 0;
        res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g));
Alan Mishchenko committed
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
    } while (dd->reordered == 1);
    res = Cudd_NotCond(res,res != NULL);
    return(res);

} /* end of Cudd_bddOr */


/**Function********************************************************************

  Synopsis    [Computes the NAND of two BDDs f and g.]

  Description [Computes the NAND of two BDDs f and g. Returns a
  pointer to the resulting BDD if successful; NULL if the intermediate
  result blows up.]

  SideEffects [None]

  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNor
  Cudd_bddXor Cudd_bddXnor]

******************************************************************************/
DdNode *
Cudd_bddNand(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    DdNode *res;

    do {
421 422
        dd->reordered = 0;
        res = cuddBddAndRecur(dd,f,g);
Alan Mishchenko committed
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
    } while (dd->reordered == 1);
    res = Cudd_NotCond(res,res != NULL);
    return(res);

} /* end of Cudd_bddNand */


/**Function********************************************************************

  Synopsis    [Computes the NOR of two BDDs f and g.]

  Description [Computes the NOR of two BDDs f and g. Returns a
  pointer to the resulting BDD if successful; NULL if the intermediate
  result blows up.]

  SideEffects [None]

  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNand
  Cudd_bddXor Cudd_bddXnor]

******************************************************************************/
DdNode *
Cudd_bddNor(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    DdNode *res;

    do {
453 454
        dd->reordered = 0;
        res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g));
Alan Mishchenko committed
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
    } while (dd->reordered == 1);
    return(res);

} /* end of Cudd_bddNor */


/**Function********************************************************************

  Synopsis    [Computes the exclusive OR of two BDDs f and g.]

  Description [Computes the exclusive OR of two BDDs f and g. Returns a
  pointer to the resulting BDD if successful; NULL if the intermediate
  result blows up.]

  SideEffects [None]

  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr
  Cudd_bddNand Cudd_bddNor Cudd_bddXnor]

******************************************************************************/
DdNode *
Cudd_bddXor(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    DdNode *res;

    do {
484 485
        dd->reordered = 0;
        res = cuddBddXorRecur(dd,f,g);
Alan Mishchenko committed
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
    } while (dd->reordered == 1);
    return(res);

} /* end of Cudd_bddXor */


/**Function********************************************************************

  Synopsis    [Computes the exclusive NOR of two BDDs f and g.]

  Description [Computes the exclusive NOR of two BDDs f and g. Returns a
  pointer to the resulting BDD if successful; NULL if the intermediate
  result blows up.]

  SideEffects [None]

  SeeAlso     [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr
  Cudd_bddNand Cudd_bddNor Cudd_bddXor]

******************************************************************************/
DdNode *
Cudd_bddXnor(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    DdNode *res;

    do {
515 516
        dd->reordered = 0;
        res = cuddBddXorRecur(dd,f,Cudd_Not(g));
Alan Mishchenko committed
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
    } while (dd->reordered == 1);
    return(res);

} /* end of Cudd_bddXnor */


/**Function********************************************************************

  Synopsis    [Determines whether f is less than or equal to g.]

  Description [Returns 1 if f is less than or equal to g; 0 otherwise.
  No new nodes are created.]

  SideEffects [None]

  SeeAlso     [Cudd_bddIteConstant Cudd_addEvalConst]

******************************************************************************/
int
Cudd_bddLeq(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    DdNode *one, *zero, *tmp, *F, *fv, *fvn, *gv, *gvn;
    unsigned int topf, topg, res;

    statLine(dd);
    /* Terminal cases and normalization. */
    if (f == g) return(1);

    if (Cudd_IsComplement(g)) {
549 550 551 552 553 554 555 556 557 558
        /* Special case: if f is regular and g is complemented,
        ** f(1,...,1) = 1 > 0 = g(1,...,1).
        */
        if (!Cudd_IsComplement(f)) return(0);
        /* Both are complemented: Swap and complement because
        ** f <= g <=> g' <= f' and we want the second argument to be regular.
        */
        tmp = g;
        g = Cudd_Not(f);
        f = Cudd_Not(tmp);
559
    } else if (Cudd_IsComplement(f) && cuddF2L(g) < cuddF2L(f)) {
560 561 562
        tmp = g;
        g = Cudd_Not(f);
        f = Cudd_Not(tmp);
Alan Mishchenko committed
563 564 565 566 567 568 569 570 571 572 573 574 575
    }

    /* Now g is regular and, if f is not regular, f < g. */
    one = DD_ONE(dd);
    if (g == one) return(1);    /* no need to test against zero */
    if (f == one) return(0);    /* since at this point g != one */
    if (Cudd_Not(f) == g) return(0); /* because neither is constant */
    zero = Cudd_Not(one);
    if (f == zero) return(1);

    /* Here neither f nor g is constant. */

    /* Check cache. */
576
    tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_bddLeq,f,g);
Alan Mishchenko committed
577
    if (tmp != NULL) {
578
        return(tmp == one);
Alan Mishchenko committed
579 580 581 582 583 584 585
    }

    /* Compute cofactors. */
    F = Cudd_Regular(f);
    topf = dd->perm[F->index];
    topg = dd->perm[g->index];
    if (topf <= topg) {
586 587 588 589 590
        fv = cuddT(F); fvn = cuddE(F);
        if (f != F) {
            fv = Cudd_Not(fv);
            fvn = Cudd_Not(fvn);
        }
Alan Mishchenko committed
591
    } else {
592
        fv = fvn = f;
Alan Mishchenko committed
593 594
    }
    if (topg <= topf) {
595
        gv = cuddT(g); gvn = cuddE(g);
Alan Mishchenko committed
596
    } else {
597
        gv = gvn = g;
Alan Mishchenko committed
598 599 600 601 602 603 604 605 606 607
    }

    /* Recursive calls. Since we want to maximize the probability of
    ** the special case f(1,...,1) > g(1,...,1), we consider the negative
    ** cofactors first. Indeed, the complementation parity of the positive
    ** cofactors is the same as the one of the parent functions.
    */
    res = Cudd_bddLeq(dd,fvn,gvn) && Cudd_bddLeq(dd,fv,gv);

    /* Store result in cache and return. */
608
    cuddCacheInsert2(dd,(DD_CTFP)Cudd_bddLeq,f,g,(res ? one : zero));
Alan Mishchenko committed
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
    return(res);

} /* end of Cudd_bddLeq */


/*---------------------------------------------------------------------------*/
/* Definition of internal functions                                          */
/*---------------------------------------------------------------------------*/


/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_bddIte.]

  Description [Implements the recursive step of Cudd_bddIte. Returns a
  pointer to the resulting BDD. NULL if the intermediate result blows
  up or if reordering occurs.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
DdNode *
cuddBddIteRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  DdNode * h)
{
639 640
    DdNode       *one, *zero, *res;
    DdNode       *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
Alan Mishchenko committed
641
    unsigned int topf, topg, toph, v;
642
    int          index = -1;
643
    int          comple;
Alan Mishchenko committed
644 645 646 647 648

    statLine(dd);
    /* Terminal cases. */

    /* One variable cases. */
649 650
    if (f == (one = DD_ONE(dd)))        /* ITE(1,G,H) = G */
        return(g);
Alan Mishchenko committed
651
    
652 653
    if (f == (zero = Cudd_Not(one)))    /* ITE(0,G,H) = H */
        return(h);
Alan Mishchenko committed
654 655
    
    /* From now on, f is known not to be a constant. */
656 657 658 659 660 661 662
    if (g == one || f == g) {   /* ITE(F,F,H) = ITE(F,1,H) = F + H */
        if (h == zero) {        /* ITE(F,1,0) = F */
            return(f);
        } else {
            res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h));
            return(Cudd_NotCond(res,res != NULL));
        }
Alan Mishchenko committed
663
    } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
664 665 666 667 668 669
        if (h == one) {         /* ITE(F,0,1) = !F */
            return(Cudd_Not(f));
        } else {
            res = cuddBddAndRecur(dd,Cudd_Not(f),h);
            return(res);
        }
Alan Mishchenko committed
670 671
    }
    if (h == zero || f == h) {    /* ITE(F,G,F) = ITE(F,G,0) = F * G */
672 673
        res = cuddBddAndRecur(dd,f,g);
        return(res);
Alan Mishchenko committed
674
    } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
675 676
        res = cuddBddAndRecur(dd,f,Cudd_Not(g));
        return(Cudd_NotCond(res,res != NULL));
Alan Mishchenko committed
677 678 679
    }

    /* Check remaining one variable case. */
680 681
    if (g == h) {               /* ITE(F,G,G) = G */
        return(g);
Alan Mishchenko committed
682
    } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */
683 684
        res = cuddBddXorRecur(dd,f,h);
        return(res);
Alan Mishchenko committed
685 686 687 688 689 690 691 692 693 694 695
    }
    
    /* From here, there are no constants. */
    comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph);

    /* f & g are now regular pointers */

    v = ddMin(topg, toph);

    /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */
    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
696 697
        r = cuddUniqueInter(dd, (int) f->index, g, h);
        return(Cudd_NotCond(r,comple && r != NULL));
Alan Mishchenko committed
698 699 700 701 702
    }

    /* Check cache. */
    r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h);
    if (r != NULL) {
703
        return(Cudd_NotCond(r,comple));
Alan Mishchenko committed
704 705 706 707
    }

    /* Compute cofactors. */
    if (topf <= v) {
708 709 710
        v = ddMin(topf, v);     /* v = top_var(F,G,H) */
        index = f->index;
        Fv = cuddT(f); Fnv = cuddE(f);
Alan Mishchenko committed
711
    } else {
712
        Fv = Fnv = f;
Alan Mishchenko committed
713 714
    }
    if (topg == v) {
715 716
        index = g->index;
        Gv = cuddT(g); Gnv = cuddE(g);
Alan Mishchenko committed
717
    } else {
718
        Gv = Gnv = g;
Alan Mishchenko committed
719 720
    }
    if (toph == v) {
721 722 723 724 725 726 727
        H = Cudd_Regular(h);
        index = H->index;
        Hv = cuddT(H); Hnv = cuddE(H);
        if (Cudd_IsComplement(h)) {
            Hv = Cudd_Not(Hv);
            Hnv = Cudd_Not(Hnv);
        }
Alan Mishchenko committed
728
    } else {
729
        Hv = Hnv = h;
Alan Mishchenko committed
730 731 732 733 734 735 736 737 738
    }

    /* Recursive step. */
    t = cuddBddIteRecur(dd,Fv,Gv,Hv);
    if (t == NULL) return(NULL);
    cuddRef(t);

    e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv);
    if (e == NULL) {
739 740
        Cudd_IterDerefBdd(dd,t);
        return(NULL);
Alan Mishchenko committed
741 742 743 744 745
    }
    cuddRef(e);

    r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
    if (r == NULL) {
746 747 748
        Cudd_IterDerefBdd(dd,t);
        Cudd_IterDerefBdd(dd,e);
        return(NULL);
Alan Mishchenko committed
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
    }
    cuddDeref(t);
    cuddDeref(e);

    cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r);
    return(Cudd_NotCond(r,comple));

} /* end of cuddBddIteRecur */


/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_bddIntersect.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_bddIntersect]

******************************************************************************/
DdNode *
cuddBddIntersectRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    DdNode *res;
    DdNode *F, *G, *t, *e;
    DdNode *fv, *fnv, *gv, *gnv;
    DdNode *one, *zero;
    unsigned int index, topf, topg;

    statLine(dd);
    one = DD_ONE(dd);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
    if (f == g || g == one) return(f);
    if (f == one) return(g);

    /* At this point f and g are not constant. */
792
    if (cuddF2L(f) > cuddF2L(g)) { DdNode *tmp = f; f = g; g = tmp; }
Alan Mishchenko committed
793 794 795 796 797 798 799 800 801 802 803 804 805
    res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g);
    if (res != NULL) return(res);

    /* Find splitting variable. Here we can skip the use of cuddI,
    ** because the operands are known to be non-constant.
    */
    F = Cudd_Regular(f);
    topf = dd->perm[F->index];
    G = Cudd_Regular(g);
    topg = dd->perm[G->index];

    /* Compute cofactors. */
    if (topf <= topg) {
806 807 808 809 810 811 812
        index = F->index;
        fv = cuddT(F);
        fnv = cuddE(F);
        if (Cudd_IsComplement(f)) {
            fv = Cudd_Not(fv);
            fnv = Cudd_Not(fnv);
        }
Alan Mishchenko committed
813
    } else {
814 815
        index = G->index;
        fv = fnv = f;
Alan Mishchenko committed
816 817 818
    }

    if (topg <= topf) {
819 820 821 822 823 824
        gv = cuddT(G);
        gnv = cuddE(G);
        if (Cudd_IsComplement(g)) {
            gv = Cudd_Not(gv);
            gnv = Cudd_Not(gnv);
        }
Alan Mishchenko committed
825
    } else {
826
        gv = gnv = g;
Alan Mishchenko committed
827 828 829 830 831 832 833
    }

    /* Compute partial results. */
    t = cuddBddIntersectRecur(dd,fv,gv);
    if (t == NULL) return(NULL);
    cuddRef(t);
    if (t != zero) {
834
        e = zero;
Alan Mishchenko committed
835
    } else {
836 837 838 839 840
        e = cuddBddIntersectRecur(dd,fnv,gnv);
        if (e == NULL) {
            Cudd_IterDerefBdd(dd, t);
            return(NULL);
        }
Alan Mishchenko committed
841 842 843 844
    }
    cuddRef(e);

    if (t == e) { /* both equal zero */
845
        res = t;
Alan Mishchenko committed
846
    } else if (Cudd_IsComplement(t)) {
847 848 849 850 851 852 853
        res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e));
        if (res == NULL) {
            Cudd_IterDerefBdd(dd, t);
            Cudd_IterDerefBdd(dd, e);
            return(NULL);
        }
        res = Cudd_Not(res);
Alan Mishchenko committed
854
    } else {
855 856 857 858 859 860
        res = cuddUniqueInter(dd,(int)index,t,e);
        if (res == NULL) {
            Cudd_IterDerefBdd(dd, t);
            Cudd_IterDerefBdd(dd, e);
            return(NULL);
        }
Alan Mishchenko committed
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
    }
    cuddDeref(e);
    cuddDeref(t);

    cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res);

    return(res);

} /* end of cuddBddIntersectRecur */


/**Function********************************************************************

  Synopsis [Implements the recursive step of Cudd_bddAnd.]

  Description [Implements the recursive step of Cudd_bddAnd by taking
  the conjunction of two BDDs.  Returns a pointer to the result is
  successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddAnd]

******************************************************************************/
DdNode *
cuddBddAndRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g)
{
    DdNode *F, *fv, *fnv, *G, *gv, *gnv;
    DdNode *one, *r, *t, *e;
    unsigned int topf, topg, index;

    statLine(manager);
    one = DD_ONE(manager);

    /* Terminal cases. */
    F = Cudd_Regular(f);
    G = Cudd_Regular(g);
    if (F == G) {
902 903
        if (f == g) return(f);
        else return(Cudd_Not(one));
Alan Mishchenko committed
904 905
    }
    if (F == one) {
906 907
        if (f == one) return(g);
        else return(f);
Alan Mishchenko committed
908 909
    }
    if (G == one) {
910 911
        if (g == one) return(f);
        else return(g);
Alan Mishchenko committed
912 913 914
    }

    /* At this point f and g are not constant. */
915
    if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency. */
916 917 918 919 920
        DdNode *tmp = f;
        f = g;
        g = tmp;
        F = Cudd_Regular(f);
        G = Cudd_Regular(g);
Alan Mishchenko committed
921 922 923 924
    }

    /* Check cache. */
    if (F->ref != 1 || G->ref != 1) {
925 926
        r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g);
        if (r != NULL) return(r);
Alan Mishchenko committed
927 928
    }

929
    if ( manager->TimeStop && Abc_Clock() > manager->TimeStop )
930 931
        return NULL;

Alan Mishchenko committed
932 933 934 935 936 937 938 939
    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    topf = manager->perm[F->index];
    topg = manager->perm[G->index];

    /* Compute cofactors. */
    if (topf <= topg) {
940 941 942 943 944 945 946
        index = F->index;
        fv = cuddT(F);
        fnv = cuddE(F);
        if (Cudd_IsComplement(f)) {
            fv = Cudd_Not(fv);
            fnv = Cudd_Not(fnv);
        }
Alan Mishchenko committed
947
    } else {
948 949
        index = G->index;
        fv = fnv = f;
Alan Mishchenko committed
950 951 952
    }

    if (topg <= topf) {
953 954 955 956 957 958
        gv = cuddT(G);
        gnv = cuddE(G);
        if (Cudd_IsComplement(g)) {
            gv = Cudd_Not(gv);
            gnv = Cudd_Not(gnv);
        }
Alan Mishchenko committed
959
    } else {
960
        gv = gnv = g;
Alan Mishchenko committed
961 962 963 964 965 966 967 968
    }

    t = cuddBddAndRecur(manager, fv, gv);
    if (t == NULL) return(NULL);
    cuddRef(t);

    e = cuddBddAndRecur(manager, fnv, gnv);
    if (e == NULL) {
969 970
        Cudd_IterDerefBdd(manager, t);
        return(NULL);
Alan Mishchenko committed
971 972 973 974
    }
    cuddRef(e);

    if (t == e) {
975
        r = t;
Alan Mishchenko committed
976
    } else {
977 978 979 980 981 982 983 984 985 986 987 988 989 990 991
        if (Cudd_IsComplement(t)) {
            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
            r = Cudd_Not(r);
        } else {
            r = cuddUniqueInter(manager,(int)index,t,e);
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
Alan Mishchenko committed
992 993 994 995 996
        }
    }
    cuddDeref(e);
    cuddDeref(t);
    if (F->ref != 1 || G->ref != 1)
997
        cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r);
Alan Mishchenko committed
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
    return(r);

} /* end of cuddBddAndRecur */


/**Function********************************************************************

  Synopsis [Implements the recursive step of Cudd_bddXor.]

  Description [Implements the recursive step of Cudd_bddXor by taking
  the exclusive OR of two BDDs.  Returns a pointer to the result is
  successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddXor]

******************************************************************************/
DdNode *
cuddBddXorRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g)
{
    DdNode *fv, *fnv, *G, *gv, *gnv;
    DdNode *one, *zero, *r, *t, *e;
    unsigned int topf, topg, index;

    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == g) return(zero);
    if (f == Cudd_Not(g)) return(one);
1033
    if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency and simplify tests. */
1034 1035 1036
        DdNode *tmp = f;
        f = g;
        g = tmp;
Alan Mishchenko committed
1037 1038 1039 1040
    }
    if (g == zero) return(f);
    if (g == one) return(Cudd_Not(f));
    if (Cudd_IsComplement(f)) {
1041 1042
        f = Cudd_Not(f);
        g = Cudd_Not(g);
Alan Mishchenko committed
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
    }
    /* Now the first argument is regular. */
    if (f == one) return(Cudd_Not(g));

    /* At this point f and g are not constant. */

    /* Check cache. */
    r = cuddCacheLookup2(manager, Cudd_bddXor, f, g);
    if (r != NULL) return(r);

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    topf = manager->perm[f->index];
    G = Cudd_Regular(g);
    topg = manager->perm[G->index];

    /* Compute cofactors. */
    if (topf <= topg) {
1062 1063 1064
        index = f->index;
        fv = cuddT(f);
        fnv = cuddE(f);
Alan Mishchenko committed
1065
    } else {
1066 1067
        index = G->index;
        fv = fnv = f;
Alan Mishchenko committed
1068 1069 1070
    }

    if (topg <= topf) {
1071 1072 1073 1074 1075 1076
        gv = cuddT(G);
        gnv = cuddE(G);
        if (Cudd_IsComplement(g)) {
            gv = Cudd_Not(gv);
            gnv = Cudd_Not(gnv);
        }
Alan Mishchenko committed
1077
    } else {
1078
        gv = gnv = g;
Alan Mishchenko committed
1079 1080 1081 1082 1083 1084 1085 1086
    }

    t = cuddBddXorRecur(manager, fv, gv);
    if (t == NULL) return(NULL);
    cuddRef(t);

    e = cuddBddXorRecur(manager, fnv, gnv);
    if (e == NULL) {
1087 1088
        Cudd_IterDerefBdd(manager, t);
        return(NULL);
Alan Mishchenko committed
1089 1090 1091 1092
    }
    cuddRef(e);

    if (t == e) {
1093
        r = t;
Alan Mishchenko committed
1094
    } else {
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
        if (Cudd_IsComplement(t)) {
            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
            r = Cudd_Not(r);
        } else {
            r = cuddUniqueInter(manager,(int)index,t,e);
            if (r == NULL) {
                Cudd_IterDerefBdd(manager, t);
                Cudd_IterDerefBdd(manager, e);
                return(NULL);
            }
Alan Mishchenko committed
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
        }
    }
    cuddDeref(e);
    cuddDeref(t);
    cuddCacheInsert2(manager, Cudd_bddXor, f, g, r);
    return(r);

} /* end of cuddBddXorRecur */


/*---------------------------------------------------------------------------*/
/* Definition of static functions                                            */
/*---------------------------------------------------------------------------*/


/**Function********************************************************************

  Synopsis [Replaces variables with constants if possible.]

  Description [This function performs part of the transformation to
  standard form by replacing variables with constants if possible.]

  SideEffects [None]

  SeeAlso     [bddVarToCanonical bddVarToCanonicalSimple]

******************************************************************************/
static void
bddVarToConst(
  DdNode * f,
  DdNode ** gp,
  DdNode ** hp,
  DdNode * one)
{
    DdNode *g = *gp;
    DdNode *h = *hp;

    if (f == g) {    /* ITE(F,F,H) = ITE(F,1,H) = F + H */
1148
        *gp = one;
Alan Mishchenko committed
1149
    } else if (f == Cudd_Not(g)) {    /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
1150
        *gp = Cudd_Not(one);
Alan Mishchenko committed
1151 1152
    }
    if (f == h) {    /* ITE(F,G,F) = ITE(F,G,0) = F * G */
1153
        *hp = Cudd_Not(one);
Alan Mishchenko committed
1154
    } else if (f == Cudd_Not(h)) {    /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
1155
        *hp = one;
Alan Mishchenko committed
1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181
    }

} /* end of bddVarToConst */


/**Function********************************************************************

  Synopsis [Picks unique member from equiv expressions.]

  Description [Reduces 2 variable expressions to canonical form.]

  SideEffects [None]

  SeeAlso     [bddVarToConst bddVarToCanonicalSimple]

******************************************************************************/
static int
bddVarToCanonical(
  DdManager * dd,
  DdNode ** fp,
  DdNode ** gp,
  DdNode ** hp,
  unsigned int * topfp,
  unsigned int * topgp,
  unsigned int * tophp)
{
1182 1183 1184 1185
    register DdNode             *F, *G, *H, *r, *f, *g, *h;
    register unsigned int       topf, topg, toph;
    DdNode                      *one = dd->one;
    int                         comple, change;
Alan Mishchenko committed
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198

    f = *fp;
    g = *gp;
    h = *hp;
    F = Cudd_Regular(f);
    G = Cudd_Regular(g);
    H = Cudd_Regular(h);
    topf = cuddI(dd,F->index);
    topg = cuddI(dd,G->index);
    toph = cuddI(dd,H->index);

    change = 0;

1199
    if (G == one) {                     /* ITE(F,c,H) */
1200
        if ((topf > toph) || (topf == toph && cuddF2L(f) > cuddF2L(h))) {
1201 1202 1203 1204 1205 1206 1207 1208
            r = h;
            h = f;
            f = r;                      /* ITE(F,1,H) = ITE(H,1,F) */
            if (g != one) {     /* g == zero */
                f = Cudd_Not(f);                /* ITE(F,0,H) = ITE(!H,0,!F) */
                h = Cudd_Not(h);
            }
            change = 1;
Alan Mishchenko committed
1209
        }
1210
    } else if (H == one) {              /* ITE(F,G,c) */
1211
        if ((topf > topg) || (topf == topg && cuddF2L(f) > cuddF2L(g))) {
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221
            r = g;
            g = f;
            f = r;                      /* ITE(F,G,0) = ITE(G,F,0) */
            if (h == one) {
                f = Cudd_Not(f);                /* ITE(F,G,1) = ITE(!G,!F,1) */
                g = Cudd_Not(g);
            }
            change = 1;
        }
    } else if (g == Cudd_Not(h)) {      /* ITE(F,G,!G) = ITE(G,F,!F) */
1222
        if ((topf > topg) || (topf == topg && cuddF2L(f) > cuddF2L(g))) {
1223 1224 1225 1226 1227
            r = f;
            f = g;
            g = r;
            h = Cudd_Not(r);
            change = 1;
Alan Mishchenko committed
1228 1229 1230 1231
        }
    }
    /* adjust pointers so that the first 2 arguments to ITE are regular */
    if (Cudd_IsComplement(f) != 0) {    /* ITE(!F,G,H) = ITE(F,H,G) */
1232 1233 1234 1235 1236
        f = Cudd_Not(f);
        r = g;
        g = h;
        h = r;
        change = 1;
Alan Mishchenko committed
1237 1238 1239
    }
    comple = 0;
    if (Cudd_IsComplement(g) != 0) {    /* ITE(F,!G,H) = !ITE(F,G,!H) */
1240 1241 1242 1243
        g = Cudd_Not(g);
        h = Cudd_Not(h);
        change = 1;
        comple = 1;
Alan Mishchenko committed
1244 1245
    }
    if (change != 0) {
1246 1247 1248
        *fp = f;
        *gp = g;
        *hp = h;
Alan Mishchenko committed
1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283
    }
    *topfp = cuddI(dd,f->index);
    *topgp = cuddI(dd,g->index);
    *tophp = cuddI(dd,Cudd_Regular(h)->index);

    return(comple);

} /* end of bddVarToCanonical */


/**Function********************************************************************

  Synopsis [Picks unique member from equiv expressions.]

  Description [Makes sure the first two pointers are regular.  This
  mat require the complementation of the result, which is signaled by
  returning 1 instead of 0.  This function is simpler than the general
  case because it assumes that no two arguments are the same or
  complementary, and no argument is constant.]

  SideEffects [None]

  SeeAlso     [bddVarToConst bddVarToCanonical]

******************************************************************************/
static int
bddVarToCanonicalSimple(
  DdManager * dd,
  DdNode ** fp,
  DdNode ** gp,
  DdNode ** hp,
  unsigned int * topfp,
  unsigned int * topgp,
  unsigned int * tophp)
{
1284 1285
    register DdNode             *r, *f, *g, *h;
    int                         comple, change;
Alan Mishchenko committed
1286 1287 1288 1289 1290 1291 1292 1293

    f = *fp;
    g = *gp;
    h = *hp;

    change = 0;

    /* adjust pointers so that the first 2 arguments to ITE are regular */
1294 1295 1296 1297 1298 1299
    if (Cudd_IsComplement(f)) { /* ITE(!F,G,H) = ITE(F,H,G) */
        f = Cudd_Not(f);
        r = g;
        g = h;
        h = r;
        change = 1;
Alan Mishchenko committed
1300 1301
    }
    comple = 0;
1302 1303 1304 1305 1306
    if (Cudd_IsComplement(g)) { /* ITE(F,!G,H) = !ITE(F,G,!H) */
        g = Cudd_Not(g);
        h = Cudd_Not(h);
        change = 1;
        comple = 1;
Alan Mishchenko committed
1307 1308
    }
    if (change) {
1309 1310 1311
        *fp = f;
        *gp = g;
        *hp = h;
Alan Mishchenko committed
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
    }

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    *topfp = dd->perm[f->index];
    *topgp = dd->perm[g->index];
    *tophp = dd->perm[Cudd_Regular(h)->index];

    return(comple);

} /* end of bddVarToCanonicalSimple */

1325

1326 1327
ABC_NAMESPACE_IMPL_END

1328