@@ -1415,11 +1415,6 @@ literalt bv_utilst::lt_or_le(
14151415#ifdef COMPACT_LT_OR_LE
14161416 if (prop.has_set_to () && prop.cnf_handled_well ())
14171417 {
1418- bvt compareBelow; // 1 if a compare is needed below this bit
1419- literalt result;
1420- size_t start;
1421- size_t i;
1422-
14231418 if (rep == representationt::SIGNED)
14241419 {
14251420 if (top0.is_false () && top1.is_true ())
@@ -1429,8 +1424,9 @@ literalt bv_utilst::lt_or_le(
14291424
14301425 INVARIANT (
14311426 bv0.size () >= 2 , " signed bitvectors should have at least two bits" );
1432- compareBelow = prop.new_variables (bv0.size () - 1 );
1433- start = compareBelow.size () - 1 ;
1427+ // 1 if a compare is needed below this bit
1428+ bvt compareBelow = prop.new_variables (bv0.size () - 1 );
1429+ size_t start = compareBelow.size () - 1 ;
14341430
14351431 literalt &firstComp = compareBelow[start];
14361432 if (top0.is_false ())
@@ -1442,7 +1438,7 @@ literalt bv_utilst::lt_or_le(
14421438 else if (top1.is_true ())
14431439 firstComp = top0;
14441440
1445- result = prop.new_variable ();
1441+ literalt result = prop.new_variable ();
14461442
14471443 // When comparing signs we are comparing the top bit
14481444 // Four cases...
@@ -1454,70 +1450,130 @@ literalt bv_utilst::lt_or_le(
14541450#ifdef INCLUDE_REDUNDANT_CLAUSES
14551451 prop.lcnf (top0, !top1, !firstComp);
14561452 prop.lcnf (!top0, top1, !firstComp);
1457- #endif
1458- }
1459- else
1460- {
1461- // Unsigned is much easier
1462- compareBelow = prop.new_variables (bv0.size () - 1 );
1463- compareBelow.push_back (const_literal (true ));
1464- start = compareBelow.size () - 1 ;
1465- result = prop.new_variable ();
1466- }
1453+ # endif
14671454
1468- // Determine the output
1469- // \forall i . cb[i] & -a[i] & b[i] => result
1470- // \forall i . cb[i] & a[i] & -b[i] => -result
1471- i = start;
1472- do
1473- {
1474- if (compareBelow[i].is_false ())
1475- continue ;
1476- else if (compareBelow[i].is_true ())
1455+ // Determine the output
1456+ // \forall i . cb[i] & -a[i] & b[i] => result
1457+ // \forall i . cb[i] & a[i] & -b[i] => -result
1458+ size_t i = start;
1459+ do
14771460 {
1478- if (bv0[i].is_false () && bv1[i].is_true ())
1479- return const_literal (true );
1480- else if (bv0[i].is_true () && bv1[i].is_false ())
1481- return const_literal (false );
1461+ if (compareBelow[i].is_false ())
1462+ continue ;
1463+
1464+ prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], result);
1465+ prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !result);
1466+ } while (i-- != 0 );
1467+
1468+ // Chain the comparison bit
1469+ // \forall i != 0 . cb[i] & a[i] & b[i] => cb[i-1]
1470+ // \forall i != 0 . cb[i] & -a[i] & -b[i] => cb[i-1]
1471+ for (i = start; i > 0 ; i--)
1472+ {
1473+ prop.lcnf (!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i - 1 ]);
1474+ prop.lcnf (!compareBelow[i], bv0[i], bv1[i], compareBelow[i - 1 ]);
14821475 }
14831476
1484- prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], result);
1485- prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !result);
1486- }
1487- while (i-- != 0 );
1477+ # ifdef INCLUDE_REDUNDANT_CLAUSES
1478+ // Optional zeroing of the comparison bit when not needed
1479+ // \forall i != 0 . -c[i] => -c[i-1]
1480+ // \forall i != 0 . c[i] & -a[i] & b[i] => -c[i-1]
1481+ // \forall i != 0 . c[i] & a[i] & -b[i] => -c[i-1]
1482+ for (i = start; i > 0 ; i--)
1483+ {
1484+ prop.lcnf (compareBelow[i], !compareBelow[i - 1 ]);
1485+ prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i - 1 ]);
1486+ prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i - 1 ]);
1487+ }
1488+ # endif
14881489
1489- // Chain the comparison bit
1490- // \forall i != 0 . cb[i] & a[i] & b[i] => cb[i-1]
1491- // \forall i != 0 . cb[i] & -a[i] & -b[i] => cb[i-1]
1492- for (i = start; i > 0 ; i--)
1493- {
1494- prop.lcnf (!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i-1 ]);
1495- prop.lcnf (!compareBelow[i], bv0[i], bv1[i], compareBelow[i-1 ]);
1496- }
1490+ // The 'base case' of the induction is the case when they are equal
1491+ prop.lcnf (
1492+ !compareBelow[0 ], !bv0[0 ], !bv1[0 ], (or_equal) ? result : !result);
1493+ prop.lcnf (
1494+ !compareBelow[0 ], bv0[0 ], bv1[0 ], (or_equal) ? result : !result);
14971495
1496+ return result;
1497+ }
1498+ else
1499+ {
1500+ // Unsigned is much easier
1501+ // 1 if a compare is needed below this bit
1502+ bvt compareBelow;
1503+ literalt result;
1504+ size_t start = bv0.size () - 1 ;
1505+
1506+ // Determine the output
1507+ // \forall i . cb[i] & -a[i] & b[i] => result
1508+ // \forall i . cb[i] & a[i] & -b[i] => -result
1509+ bool same_prefix = true ;
1510+ size_t i = start;
1511+ do
1512+ {
1513+ if (same_prefix)
1514+ {
1515+ if (i == 0 )
1516+ {
1517+ if (or_equal)
1518+ return prop.lor (!bv0[0 ], bv1[0 ]);
1519+ else
1520+ return prop.land (!bv0[0 ], bv1[0 ]);
1521+ }
1522+ else if (bv0[i] == bv1[i])
1523+ continue ;
1524+ else if (bv0[i].is_false () && bv1[i].is_true ())
1525+ return const_literal (true );
1526+ else if (bv0[i].is_true () && bv1[i].is_false ())
1527+ return const_literal (false );
1528+ else
1529+ {
1530+ same_prefix = false ;
1531+ start = i;
1532+ compareBelow = prop.new_variables (i);
1533+ compareBelow.push_back (const_literal (true ));
1534+ result = prop.new_variable ();
1535+ }
1536+ }
1537+
1538+ prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], result);
1539+ prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !result);
1540+ } while (i-- != 0 );
1541+
1542+ // Chain the comparison bit
1543+ // \forall i != 0 . cb[i] & a[i] & b[i] => cb[i-1]
1544+ // \forall i != 0 . cb[i] & -a[i] & -b[i] => cb[i-1]
1545+ for (i = start; i > 0 ; i--)
1546+ {
1547+ prop.lcnf (!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i - 1 ]);
1548+ prop.lcnf (!compareBelow[i], bv0[i], bv1[i], compareBelow[i - 1 ]);
1549+ }
14981550
14991551#ifdef INCLUDE_REDUNDANT_CLAUSES
1500- // Optional zeroing of the comparison bit when not needed
1501- // \forall i != 0 . -c[i] => -c[i-1]
1502- // \forall i != 0 . c[i] & -a[i] & b[i] => -c[i-1]
1503- // \forall i != 0 . c[i] & a[i] & -b[i] => -c[i-1]
1504- for (i = start; i > 0 ; i--)
1505- {
1506- prop.lcnf (compareBelow[i], !compareBelow[i- 1 ]);
1507- prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i- 1 ]);
1508- prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i- 1 ]);
1509- }
1552+ // Optional zeroing of the comparison bit when not needed
1553+ // \forall i != 0 . -c[i] => -c[i-1]
1554+ // \forall i != 0 . c[i] & -a[i] & b[i] => -c[i-1]
1555+ // \forall i != 0 . c[i] & a[i] & -b[i] => -c[i-1]
1556+ for (i = start; i > 0 ; i--)
1557+ {
1558+ prop.lcnf (compareBelow[i], !compareBelow[i - 1 ]);
1559+ prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i - 1 ]);
1560+ prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i - 1 ]);
1561+ }
15101562#endif
15111563
1512- // The 'base case' of the induction is the case when they are equal
1513- prop.lcnf (!compareBelow[0 ], !bv0[0 ], !bv1[0 ], (or_equal)?result:!result);
1514- prop.lcnf (!compareBelow[0 ], bv0[0 ], bv1[0 ], (or_equal)?result:!result);
1564+ // The 'base case' of the induction is the case when they are equal
1565+ prop.lcnf (
1566+ !compareBelow[0 ], !bv0[0 ], !bv1[0 ], (or_equal) ? result : !result);
1567+ prop.lcnf (
1568+ !compareBelow[0 ], bv0[0 ], bv1[0 ], (or_equal) ? result : !result);
15151569
1516- return result;
1570+ return result;
1571+ }
15171572 }
15181573 else
15191574#endif
15201575 {
1576+ // A <= B iff there is an overflow on A-B
15211577 literalt carry=
15221578 carry_out (bv0, inverted (bv1), const_literal (true ));
15231579
@@ -1544,12 +1600,7 @@ literalt bv_utilst::unsigned_less_than(
15441600 const bvt &op0,
15451601 const bvt &op1)
15461602{
1547- #ifdef COMPACT_LT_OR_LE
15481603 return lt_or_le (false , op0, op1, representationt::UNSIGNED);
1549- #else
1550- // A <= B iff there is an overflow on A-B
1551- return !carry_out (op0, inverted (op1), const_literal (true ));
1552- #endif
15531604}
15541605
15551606literalt bv_utilst::signed_less_than (
0 commit comments