@@ -1411,11 +1411,6 @@ literalt bv_utilst::lt_or_le(
14111411#ifdef COMPACT_LT_OR_LE
14121412 if (prop.has_set_to () && prop.cnf_handled_well ())
14131413 {
1414- bvt compareBelow; // 1 if a compare is needed below this bit
1415- literalt result;
1416- size_t start;
1417- size_t i;
1418-
14191414 if (rep == representationt::SIGNED)
14201415 {
14211416 literalt top0 = sign_bit (bv0), top1 = sign_bit (bv1);
@@ -1427,8 +1422,9 @@ literalt bv_utilst::lt_or_le(
14271422
14281423 INVARIANT (
14291424 bv0.size () >= 2 , " signed bitvectors should have at least two bits" );
1430- compareBelow = prop.new_variables (bv0.size () - 1 );
1431- start = compareBelow.size () - 1 ;
1425+ // 1 if a compare is needed below this bit
1426+ bvt compareBelow = prop.new_variables (bv0.size () - 1 );
1427+ size_t start = compareBelow.size () - 1 ;
14321428
14331429 literalt &firstComp = compareBelow[start];
14341430 if (top0.is_false ())
@@ -1440,7 +1436,7 @@ literalt bv_utilst::lt_or_le(
14401436 else if (top1.is_true ())
14411437 firstComp = top0;
14421438
1443- result = prop.new_variable ();
1439+ literalt result = prop.new_variable ();
14441440
14451441 // When comparing signs we are comparing the top bit
14461442 // Four cases...
@@ -1452,70 +1448,130 @@ literalt bv_utilst::lt_or_le(
14521448#ifdef INCLUDE_REDUNDANT_CLAUSES
14531449 prop.lcnf (top0, !top1, !firstComp);
14541450 prop.lcnf (!top0, top1, !firstComp);
1455- #endif
1456- }
1457- else
1458- {
1459- // Unsigned is much easier
1460- compareBelow = prop.new_variables (bv0.size () - 1 );
1461- compareBelow.push_back (const_literal (true ));
1462- start = compareBelow.size () - 1 ;
1463- result = prop.new_variable ();
1464- }
1451+ # endif
14651452
1466- // Determine the output
1467- // \forall i . cb[i] & -a[i] & b[i] => result
1468- // \forall i . cb[i] & a[i] & -b[i] => -result
1469- i = start;
1470- do
1471- {
1472- if (compareBelow[i].is_false ())
1473- continue ;
1474- else if (compareBelow[i].is_true ())
1453+ // Determine the output
1454+ // \forall i . cb[i] & -a[i] & b[i] => result
1455+ // \forall i . cb[i] & a[i] & -b[i] => -result
1456+ size_t i = start;
1457+ do
14751458 {
1476- if (bv0[i].is_false () && bv1[i].is_true ())
1477- return const_literal (true );
1478- else if (bv0[i].is_true () && bv1[i].is_false ())
1479- return const_literal (false );
1459+ if (compareBelow[i].is_false ())
1460+ continue ;
1461+
1462+ prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], result);
1463+ prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !result);
1464+ } while (i-- != 0 );
1465+
1466+ // Chain the comparison bit
1467+ // \forall i != 0 . cb[i] & a[i] & b[i] => cb[i-1]
1468+ // \forall i != 0 . cb[i] & -a[i] & -b[i] => cb[i-1]
1469+ for (i = start; i > 0 ; i--)
1470+ {
1471+ prop.lcnf (!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i - 1 ]);
1472+ prop.lcnf (!compareBelow[i], bv0[i], bv1[i], compareBelow[i - 1 ]);
14801473 }
14811474
1482- prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], result);
1483- prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !result);
1484- }
1485- while (i-- != 0 );
1475+ # ifdef INCLUDE_REDUNDANT_CLAUSES
1476+ // Optional zeroing of the comparison bit when not needed
1477+ // \forall i != 0 . -c[i] => -c[i-1]
1478+ // \forall i != 0 . c[i] & -a[i] & b[i] => -c[i-1]
1479+ // \forall i != 0 . c[i] & a[i] & -b[i] => -c[i-1]
1480+ for (i = start; i > 0 ; i--)
1481+ {
1482+ prop.lcnf (compareBelow[i], !compareBelow[i - 1 ]);
1483+ prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i - 1 ]);
1484+ prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i - 1 ]);
1485+ }
1486+ # endif
14861487
1487- // Chain the comparison bit
1488- // \forall i != 0 . cb[i] & a[i] & b[i] => cb[i-1]
1489- // \forall i != 0 . cb[i] & -a[i] & -b[i] => cb[i-1]
1490- for (i = start; i > 0 ; i--)
1491- {
1492- prop.lcnf (!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i-1 ]);
1493- prop.lcnf (!compareBelow[i], bv0[i], bv1[i], compareBelow[i-1 ]);
1494- }
1488+ // The 'base case' of the induction is the case when they are equal
1489+ prop.lcnf (
1490+ !compareBelow[0 ], !bv0[0 ], !bv1[0 ], (or_equal) ? result : !result);
1491+ prop.lcnf (
1492+ !compareBelow[0 ], bv0[0 ], bv1[0 ], (or_equal) ? result : !result);
14951493
1494+ return result;
1495+ }
1496+ else
1497+ {
1498+ // Unsigned is much easier
1499+ // 1 if a compare is needed below this bit
1500+ bvt compareBelow;
1501+ literalt result;
1502+ size_t start = bv0.size () - 1 ;
1503+
1504+ // Determine the output
1505+ // \forall i . cb[i] & -a[i] & b[i] => result
1506+ // \forall i . cb[i] & a[i] & -b[i] => -result
1507+ bool same_prefix = true ;
1508+ size_t i = start;
1509+ do
1510+ {
1511+ if (same_prefix)
1512+ {
1513+ if (i == 0 )
1514+ {
1515+ if (or_equal)
1516+ return prop.lor (!bv0[0 ], bv1[0 ]);
1517+ else
1518+ return prop.land (!bv0[0 ], bv1[0 ]);
1519+ }
1520+ else if (bv0[i] == bv1[i])
1521+ continue ;
1522+ else if (bv0[i].is_false () && bv1[i].is_true ())
1523+ return const_literal (true );
1524+ else if (bv0[i].is_true () && bv1[i].is_false ())
1525+ return const_literal (false );
1526+ else
1527+ {
1528+ same_prefix = false ;
1529+ start = i;
1530+ compareBelow = prop.new_variables (i);
1531+ compareBelow.push_back (const_literal (true ));
1532+ result = prop.new_variable ();
1533+ }
1534+ }
1535+
1536+ prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], result);
1537+ prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !result);
1538+ } while (i-- != 0 );
1539+
1540+ // Chain the comparison bit
1541+ // \forall i != 0 . cb[i] & a[i] & b[i] => cb[i-1]
1542+ // \forall i != 0 . cb[i] & -a[i] & -b[i] => cb[i-1]
1543+ for (i = start; i > 0 ; i--)
1544+ {
1545+ prop.lcnf (!compareBelow[i], !bv0[i], !bv1[i], compareBelow[i - 1 ]);
1546+ prop.lcnf (!compareBelow[i], bv0[i], bv1[i], compareBelow[i - 1 ]);
1547+ }
14961548
14971549#ifdef INCLUDE_REDUNDANT_CLAUSES
1498- // Optional zeroing of the comparison bit when not needed
1499- // \forall i != 0 . -c[i] => -c[i-1]
1500- // \forall i != 0 . c[i] & -a[i] & b[i] => -c[i-1]
1501- // \forall i != 0 . c[i] & a[i] & -b[i] => -c[i-1]
1502- for (i = start; i > 0 ; i--)
1503- {
1504- prop.lcnf (compareBelow[i], !compareBelow[i- 1 ]);
1505- prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i- 1 ]);
1506- prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i- 1 ]);
1507- }
1550+ // Optional zeroing of the comparison bit when not needed
1551+ // \forall i != 0 . -c[i] => -c[i-1]
1552+ // \forall i != 0 . c[i] & -a[i] & b[i] => -c[i-1]
1553+ // \forall i != 0 . c[i] & a[i] & -b[i] => -c[i-1]
1554+ for (i = start; i > 0 ; i--)
1555+ {
1556+ prop.lcnf (compareBelow[i], !compareBelow[i - 1 ]);
1557+ prop.lcnf (!compareBelow[i], bv0[i], !bv1[i], !compareBelow[i - 1 ]);
1558+ prop.lcnf (!compareBelow[i], !bv0[i], bv1[i], !compareBelow[i - 1 ]);
1559+ }
15081560#endif
15091561
1510- // The 'base case' of the induction is the case when they are equal
1511- prop.lcnf (!compareBelow[0 ], !bv0[0 ], !bv1[0 ], (or_equal)?result:!result);
1512- prop.lcnf (!compareBelow[0 ], bv0[0 ], bv1[0 ], (or_equal)?result:!result);
1562+ // The 'base case' of the induction is the case when they are equal
1563+ prop.lcnf (
1564+ !compareBelow[0 ], !bv0[0 ], !bv1[0 ], (or_equal) ? result : !result);
1565+ prop.lcnf (
1566+ !compareBelow[0 ], bv0[0 ], bv1[0 ], (or_equal) ? result : !result);
15131567
1514- return result;
1568+ return result;
1569+ }
15151570 }
15161571 else
15171572#endif
15181573 {
1574+ // A <= B iff there is an overflow on A-B
15191575 literalt carry=
15201576 carry_out (bv0, inverted (bv1), const_literal (true ));
15211577
@@ -1542,12 +1598,7 @@ literalt bv_utilst::unsigned_less_than(
15421598 const bvt &op0,
15431599 const bvt &op1)
15441600{
1545- #ifdef COMPACT_LT_OR_LE
15461601 return lt_or_le (false , op0, op1, representationt::UNSIGNED);
1547- #else
1548- // A <= B iff there is an overflow on A-B
1549- return !carry_out (op0, inverted (op1), const_literal (true ));
1550- #endif
15511602}
15521603
15531604literalt bv_utilst::signed_less_than (
0 commit comments