3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-06 03:10:25 +00:00

fixes based on unit tests

This commit is contained in:
Nikolaj Bjorner 2024-02-19 12:59:28 +07:00
parent 046db662f9
commit 991537836b
10 changed files with 363 additions and 111 deletions

View file

@ -177,7 +177,7 @@ namespace bv {
bool sls_valuation::round_down(svector<digit_t>& dst) const {
if (lt(lo, hi)) {
if (lt(lo, hi))
if (lt(dst, lo))
return false;
if (le(hi, dst)) {
set(dst, hi);
@ -324,79 +324,90 @@ namespace bv {
}
SASSERT(!has_overflow(lo));
SASSERT(!has_overflow(hi));
init_fixed();
}
//
// tighten lo/hi based on fixed bits.
// lo[bit_i] != fixedbit[bit_i]
// let bit_i be most significant bit position of disagreement.
// if fixedbit = 1, lo = 0, increment lo
// if fixedbit = 0, lo = 1, lo := fixed & bits
// (hi-1)[bit_i] != fixedbit[bit_i]
// if fixedbit = 0, hi-1 = 1, set hi-1 := 0, maximize below bit_i
// if fixedbit = 1, hi-1 = 0, hi := fixed & bits
// tighten fixed bits based on lo/hi
// lo + 1 = hi -> set bits = lo
// lo < hi, set most significant bits based on hi
//
void sls_valuation::init_fixed() {
if (eq(lo, hi))
return;
bool lo_ok = true;
for (unsigned i = 0; i < nw; ++i)
lo_ok &= (0 == (fixed[i] & (bits[i] ^ lo[i])));
if (!lo_ok) {
svector<digit_t> tmp(nw + 1);
if (get_at_least(lo, tmp)) {
if (lt(lo, hi) && lt(tmp, hi))
set(lo, tmp);
else if (gt(lo, hi))
set(lo, tmp);
for (unsigned i = bw; i-- > 0; ) {
if (!get(fixed, i))
continue;
if (get(bits, i) == get(lo, i))
continue;
if (get(bits, i)) {
set(lo, i, true);
for (unsigned j = i; j-- > 0; )
set(lo, j, get(fixed, j) && get(bits, j));
}
else if (gt(lo, hi)) {
svector<digit_t> zero(nw + 1, (unsigned) 0);
if (get_at_least(zero, tmp) && lt(tmp, hi))
set(lo, tmp);
else {
for (unsigned j = bw; j-- > 0; )
set(lo, j, get(fixed, j) && get(bits, j));
}
break;
}
bool hi_ok = true;
svector<digit_t> hi1(nw + 1, (unsigned)0);
svector<digit_t> one(nw + 1, (unsigned)0);
one[0] = 1;
digit_t c;
mpn_manager().sub(hi.data(), nw, one.data(), nw, hi1.data(), &c);
for (unsigned i = 0; i < nw; ++i)
hi_ok &= (0 == (fixed[i] & (bits[i] ^ hi1[i])));
if (!hi_ok) {
svector<digit_t> tmp(nw + 1);
if (get_at_most(hi1, tmp)) {
if (lt(tmp, hi) && (le(lo, tmp) || lt(hi, lo))) {
mpn_manager().add(tmp.data(), nw, one.data(), nw, hi1.data(), nw + 1, &c);
clear_overflow_bits(hi1);
set(hi, hi1);
}
clear_overflow_bits(hi1);
for (unsigned i = bw; i-- > 0; ) {
if (!get(fixed, i))
continue;
if (get(bits, i) == get(hi1, i))
continue;
if (get(hi1, i)) {
set(hi1, i, false);
for (unsigned j = i; j-- > 0; )
set(hi1, j, !get(fixed, j) || get(bits, j));
}
// TODO other cases
else {
for (unsigned j = bw; j-- > 0; )
set(hi1, j, get(fixed, j) && get(bits, j));
}
mpn_manager().add(hi1.data(), nw, one.data(), nw, hi.data(), nw + 1, &c);
clear_overflow_bits(hi);
break;
}
// set fixed bits based on bounds
auto set_fixed_bit = [&](unsigned i, bool b) {
if (!get(fixed, i)) {
set(fixed, i, true);
set(bits, i, b);
}
};
// set most significant bits
if (lt(lo, hi)) {
unsigned i = bw;
for (; i-- > 0; ) {
if (get(hi, i))
break;
if (!get(fixed, i)) {
set(fixed, i, true);
set(bits, i, false);
}
}
bool is_power_of2 = true;
for (unsigned j = 0; is_power_of2 && j < i; ++j)
is_power_of2 = !get(hi, j);
if (is_power_of2) {
if (!get(fixed, i)) {
set(fixed, i, true);
set(bits, i, false);
}
}
for (; i-- > 0 && !get(hi, i); )
set_fixed_bit(i, false);
if (is_power_of2(hi))
set_fixed_bit(i, false);
}
svector<digit_t> tmp(nw + 1, (unsigned)0);
mpn_manager().add(lo.data(), nw, one.data(), nw, tmp.data(), nw + 1, &c);
clear_overflow_bits(tmp);
if (eq(tmp, hi)) {
for (unsigned i = 0; i < bw; ++i) {
if (!get(fixed, i)) {
set(fixed, i, true);
set(bits, i, get(lo, i));
}
}
// lo + 1 = hi: then bits = lo
mpn_manager().add(lo.data(), nw, one.data(), nw, hi1.data(), nw + 1, &c);
clear_overflow_bits(hi1);
if (eq(hi1, hi)) {
for (unsigned i = 0; i < bw; ++i)
set_fixed_bit(i, get(lo, i));
}
SASSERT(!has_overflow(bits));
}
@ -424,4 +435,11 @@ namespace bv {
return ovfl;
}
bool sls_valuation::is_power_of2(svector<digit_t> const& src) const {
unsigned c = 0;
for (unsigned i = 0; i < nw; ++i)
c += get_num_1bits(src[i]);
return c == 1;
}
}