mirror of
https://github.com/Z3Prover/z3
synced 2025-11-11 00:22:05 +00:00
reorg to use datatypes
This commit is contained in:
parent
48026edd7f
commit
74e73f2b84
6 changed files with 414 additions and 341 deletions
|
|
@ -27,124 +27,195 @@ Author:
|
|||
|
||||
namespace bv {
|
||||
|
||||
|
||||
|
||||
class bvect : public svector<digit_t> {
|
||||
unsigned bw = 0;
|
||||
unsigned nw = 0;
|
||||
unsigned mask = 0;
|
||||
public:
|
||||
bvect() {}
|
||||
bvect(unsigned sz): svector(sz, (unsigned)0) {}
|
||||
void set_bw(unsigned bw);
|
||||
|
||||
void clear_overflow_bits();
|
||||
void set_sub(bvect const& a, bvect const& b);
|
||||
|
||||
bool is_one() const {
|
||||
SASSERT(bw > 0);
|
||||
SASSERT(!has_overflow());
|
||||
for (unsigned i = 1; i < nw; ++i)
|
||||
if (0 != (*this)[i])
|
||||
return false;
|
||||
return 1 == (*this)[0];
|
||||
}
|
||||
|
||||
bool is_ones() const {
|
||||
SASSERT(bw > 0);
|
||||
auto const& a = *this;
|
||||
for (unsigned i = 0; i + 1 < nw; ++i)
|
||||
if (0 != ~a[i])
|
||||
return false;
|
||||
return ((~a[nw - 1]) & mask) == 0;
|
||||
}
|
||||
|
||||
bool is_zero() const {
|
||||
SASSERT(bw > 0);
|
||||
auto const& a = *this;
|
||||
for (unsigned i = 0; i + 1 < nw; ++i)
|
||||
if (a[i] != 0)
|
||||
return false;
|
||||
return (a[nw - 1] & mask) == 0;
|
||||
}
|
||||
|
||||
bool has_overflow() const {
|
||||
SASSERT(bw > 0);
|
||||
for (unsigned i = bw; i < nw * sizeof(digit_t) * 8; ++i)
|
||||
if (get(i))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool get(unsigned bit_idx) const {
|
||||
return (get_bit_word(bit_idx) & get_pos_mask(bit_idx)) != 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned parity() const {
|
||||
SASSERT(bw > 0);
|
||||
SASSERT(!has_overflow());
|
||||
for (unsigned i = 0; i < nw; ++i)
|
||||
if ((*this)[i] != 0)
|
||||
return (8 * sizeof(digit_t) * i) + trailing_zeros((*this)[i]);
|
||||
return bw;
|
||||
}
|
||||
|
||||
friend bool operator==(bvect const& a, bvect const& b);
|
||||
friend bool operator<(bvect const& a, bvect const& b);
|
||||
friend bool operator>(bvect const& a, bvect const& b);
|
||||
friend bool operator<=(bvect const& a, bvect const& b);
|
||||
friend bool operator>=(bvect const& a, bvect const& b);
|
||||
|
||||
private:
|
||||
|
||||
static digit_t get_pos_mask(unsigned bit_idx) {
|
||||
return (digit_t)1 << (digit_t)(bit_idx % (8 * sizeof(digit_t)));
|
||||
}
|
||||
|
||||
digit_t get_bit_word(unsigned bit_idx) const {
|
||||
return (*this)[bit_idx / (8 * sizeof(digit_t))];
|
||||
}
|
||||
|
||||
digit_t& get_bit_word(unsigned bit_idx) {
|
||||
return (*this)[bit_idx / (8 * sizeof(digit_t))];
|
||||
}
|
||||
};
|
||||
|
||||
bool operator==(bvect const& a, bvect const& b);
|
||||
bool operator<(bvect const& a, bvect const& b);
|
||||
bool operator<=(bvect const& a, bvect const& b);
|
||||
bool operator>=(bvect const& a, bvect const& b);
|
||||
bool operator>(bvect const& a, bvect const& b);
|
||||
inline bool operator!=(bvect const& a, bvect const& b) { return !(a == b); }
|
||||
|
||||
class sls_valuation {
|
||||
protected:
|
||||
svector<digit_t> m_bits;
|
||||
bvect m_bits;
|
||||
bvect lo, hi; // range assignment to bit-vector, as wrap-around interval
|
||||
|
||||
unsigned mask;
|
||||
rational get_value(bvect const& bits) const;
|
||||
bool round_up(bvect& dst) const;
|
||||
bool round_down(bvect& dst) const;
|
||||
|
||||
std::ostream& print_bits(std::ostream& out, bvect const& bits) const;
|
||||
|
||||
|
||||
public:
|
||||
unsigned bw; // bit-width
|
||||
unsigned nw; // num words
|
||||
svector<digit_t> lo, hi; // range assignment to bit-vector, as wrap-around interval
|
||||
svector<digit_t> fixed; // bit assignment and don't care bit
|
||||
bvect fixed; // bit assignment and don't care bit
|
||||
sls_valuation(unsigned bw);
|
||||
|
||||
unsigned num_bytes() const { return (bw + 7) / 8; }
|
||||
|
||||
digit_t bits(unsigned i) const { return m_bits[i]; }
|
||||
svector<digit_t> const& bits() const { return m_bits; }
|
||||
bvect const& bits() const { return m_bits; }
|
||||
|
||||
bool get_bit(unsigned i) const { return get(m_bits, i); }
|
||||
bool try_set_bit(unsigned i, bool b) {
|
||||
if (get(fixed, i) && get_bit(i) != b)
|
||||
return false;
|
||||
set(m_bits, i, b);
|
||||
return true;
|
||||
}
|
||||
|
||||
void set_value(svector<digit_t>& bits, rational const& r);
|
||||
void get_value(svector<digit_t> const& bits, rational& r) const;
|
||||
void get(svector<digit_t>& dst) const;
|
||||
void set_value(bvect& bits, rational const& r);
|
||||
|
||||
rational get_value() const { return get_value(m_bits); }
|
||||
rational get_lo() const { return get_value(lo); }
|
||||
rational get_hi() const { return get_value(hi); }
|
||||
|
||||
void get(bvect& dst) const;
|
||||
void add_range(rational lo, rational hi);
|
||||
bool has_range() const { return lo != hi; }
|
||||
void init_fixed();
|
||||
void set1(svector<digit_t>& bits);
|
||||
|
||||
void clear_overflow_bits(svector<digit_t>& bits) const;
|
||||
bool in_range(svector<digit_t> const& bits) const;
|
||||
bool can_set(svector<digit_t> const& bits) const;
|
||||
void clear_overflow_bits(bvect& bits) const { bits.clear_overflow_bits(); }
|
||||
bool in_range(bvect const& bits) const;
|
||||
bool can_set(bvect const& bits) const;
|
||||
|
||||
bool eq(sls_valuation const& other) const { return eq(other.m_bits); }
|
||||
bool eq(bvect const& other) const { return other == m_bits; }
|
||||
|
||||
bool eq(svector<digit_t> const& other) const { return eq(other, m_bits); }
|
||||
bool eq(svector<digit_t> const& a, svector<digit_t> const& b) const;
|
||||
bool gt(svector<digit_t> const& a, svector<digit_t> const& b) const;
|
||||
bool lt(svector<digit_t> const& a, svector<digit_t> const& b) const;
|
||||
bool le(svector<digit_t> const& a, svector<digit_t> const& b) const;
|
||||
bool is_zero() const { return m_bits.is_zero(); }
|
||||
bool is_zero(bvect const& a) const { return a.is_zero(); }
|
||||
|
||||
bool is_zero() const { return is_zero(m_bits); }
|
||||
bool is_zero(svector<digit_t> const& a) const {
|
||||
for (unsigned i = 0; i < nw; ++i)
|
||||
if (a[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool is_ones() const { return is_ones(m_bits); }
|
||||
bool is_ones(svector<digit_t> const& a) const {
|
||||
auto bound = bw % (sizeof(digit_t) * 8) == 0 ? nw : nw - 1;
|
||||
for (unsigned i = 0; i < bound; ++i)
|
||||
if (a[i] != (a[i] ^ 0))
|
||||
return false;
|
||||
if (bound < nw) {
|
||||
for (unsigned i = bound * sizeof(digit_t) * 8; i < bw; ++i)
|
||||
if (!get(a, i))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool is_ones() const { return m_bits.is_ones(); }
|
||||
|
||||
bool is_one() const { return is_one(m_bits); }
|
||||
bool is_one(svector<digit_t> const& bits) const {
|
||||
if (1 != bits[0])
|
||||
return false;
|
||||
for (unsigned i = 1; i < nw; ++i)
|
||||
if (0 != bits[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool is_one() const { return m_bits.is_one(); }
|
||||
// bool is_one(bvect const& a) const { return a.is_one(); }
|
||||
|
||||
bool sign() const { return get(m_bits, bw - 1); }
|
||||
|
||||
bool has_overflow(svector<digit_t> const& bits) const {
|
||||
for (unsigned i = bw; i < nw * sizeof(digit_t) * 8; ++i)
|
||||
if (get(bits, i))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool has_overflow(bvect const& bits) const { return bits.has_overflow(); }
|
||||
|
||||
unsigned parity(svector<digit_t> const& bits) const {
|
||||
for (unsigned i = 0; i < nw; ++i)
|
||||
if (bits[i] != 0)
|
||||
return (8 * sizeof(digit_t) * i) + trailing_zeros(bits[i]);
|
||||
return bw;
|
||||
}
|
||||
unsigned parity(bvect const& bits) const { return bits.parity(); }
|
||||
|
||||
void min_feasible(svector<digit_t>& out) const;
|
||||
void max_feasible(svector<digit_t>& out) const;
|
||||
void min_feasible(bvect& out) const;
|
||||
void max_feasible(bvect& out) const;
|
||||
|
||||
// most significant bit or bw if src = 0
|
||||
unsigned msb(svector<digit_t> const& src) const;
|
||||
unsigned msb(bvect const& src) const;
|
||||
|
||||
bool is_power_of2(svector<digit_t> const& src) const;
|
||||
bool is_power_of2(bvect const& src) const;
|
||||
|
||||
// retrieve largest number at or below (above) src which is feasible
|
||||
// with respect to fixed, lo, hi.
|
||||
bool get_at_most(svector<digit_t> const& src, svector<digit_t>& dst) const;
|
||||
bool get_at_least(svector<digit_t> const& src, svector<digit_t>& dst) const;
|
||||
bool round_up(svector<digit_t>& dst) const;
|
||||
bool round_down(svector<digit_t>& dst) const;
|
||||
bool set_repair(bool try_down, svector<digit_t>& dst);
|
||||
bool get_at_most(bvect const& src, bvect& dst) const;
|
||||
bool get_at_least(bvect const& src, bvect& dst) const;
|
||||
|
||||
bool try_set(svector<digit_t> const& src) {
|
||||
bool set_repair(bool try_down, bvect& dst);
|
||||
|
||||
bool try_set(bvect const& src) {
|
||||
if (!can_set(src))
|
||||
return false;
|
||||
set(src);
|
||||
return true;
|
||||
}
|
||||
|
||||
void set(svector<digit_t> const& src) {
|
||||
void set(bvect const& src) {
|
||||
for (unsigned i = nw; i-- > 0; )
|
||||
m_bits[i] = src[i];
|
||||
clear_overflow_bits(m_bits);
|
||||
}
|
||||
|
||||
void set_zero(svector<digit_t>& out) const {
|
||||
void set_zero(bvect& out) const {
|
||||
for (unsigned i = 0; i < nw; ++i)
|
||||
out[i] = 0;
|
||||
}
|
||||
|
||||
void set_one(svector<digit_t>& out) const {
|
||||
void set_one(bvect& out) const {
|
||||
for (unsigned i = 1; i < nw; ++i)
|
||||
out[i] = 0;
|
||||
out[0] = 1;
|
||||
|
|
@ -154,7 +225,7 @@ namespace bv {
|
|||
set_zero(m_bits);
|
||||
}
|
||||
|
||||
void sub1(svector<digit_t>& out) const {
|
||||
void sub1(bvect& out) const {
|
||||
for (unsigned i = 0; i < bw; ++i) {
|
||||
if (get(out, i)) {
|
||||
set(out, i, false);
|
||||
|
|
@ -165,90 +236,72 @@ namespace bv {
|
|||
}
|
||||
}
|
||||
|
||||
void set_sub(svector<digit_t>& out, svector<digit_t> const& a, svector<digit_t> const& b) const;
|
||||
bool set_add(svector<digit_t>& out, svector<digit_t> const& a, svector<digit_t> const& b) const;
|
||||
bool set_mul(svector<digit_t>& out, svector<digit_t> const& a, svector<digit_t> const& b, bool check_overflow = true) const;
|
||||
void shift_right(svector<digit_t>& out, unsigned shift) const;
|
||||
void set_sub(bvect& out, bvect const& a, bvect const& b) const;
|
||||
bool set_add(bvect& out, bvect const& a, bvect const& b) const;
|
||||
bool set_mul(bvect& out, bvect const& a, bvect const& b, bool check_overflow = true) const;
|
||||
void shift_right(bvect& out, unsigned shift) const;
|
||||
|
||||
void set_range(svector<digit_t>& dst, unsigned lo, unsigned hi, bool b) {
|
||||
void set_range(bvect& dst, unsigned lo, unsigned hi, bool b) {
|
||||
for (unsigned i = lo; i < hi; ++i)
|
||||
set(dst, i, b);
|
||||
}
|
||||
|
||||
void set(svector<digit_t>& d, unsigned bit_idx, bool val) const {
|
||||
auto _val = static_cast<digit_t>(0 - static_cast<digit_t>(val));
|
||||
get_bit_word(d, bit_idx) ^= (_val ^ get_bit_word(d, bit_idx)) & get_pos_mask(bit_idx);
|
||||
void set(bvect& d, unsigned bit_idx, bool val) const {
|
||||
d.set(bit_idx, val);
|
||||
}
|
||||
|
||||
void set(svector<digit_t>& dst, unsigned v) const {
|
||||
void set(bvect& dst, unsigned v) const {
|
||||
dst[0] = v;
|
||||
for (unsigned i = 1; i < nw; ++i)
|
||||
dst[i] = 0;
|
||||
}
|
||||
|
||||
void set(svector<digit_t>& dst, svector<digit_t> const& src) const {
|
||||
void set(bvect& dst, bvect const& src) const {
|
||||
for (unsigned i = 0; i < nw; ++i)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
||||
bool get(svector<digit_t> const& d, unsigned bit_idx) const {
|
||||
return (get_bit_word(d, bit_idx) & get_pos_mask(bit_idx)) != 0;
|
||||
bool get(bvect const& d, unsigned bit_idx) const {
|
||||
return d.get(bit_idx);
|
||||
}
|
||||
|
||||
unsigned to_nat(svector<digit_t> const& d, unsigned max_n);
|
||||
|
||||
|
||||
unsigned to_nat(unsigned max_n);
|
||||
|
||||
std::ostream& display(std::ostream& out) const {
|
||||
out << "V:";
|
||||
out << std::hex;
|
||||
auto print_bits = [&](svector<digit_t> const& v) {
|
||||
bool nz = false;
|
||||
for (unsigned i = nw; i-- > 0;)
|
||||
if (nz)
|
||||
out << std::setw(8) << std::setfill('0') << v[i];
|
||||
else if (v[i] != 0)
|
||||
out << v[i], nz = true;
|
||||
if (!nz)
|
||||
out << "0";
|
||||
};
|
||||
|
||||
print_bits(m_bits);
|
||||
print_bits(out, m_bits);
|
||||
out << " fix:";
|
||||
print_bits(fixed);
|
||||
print_bits(out, fixed);
|
||||
|
||||
if (!eq(lo, hi)) {
|
||||
if (lo != hi) {
|
||||
out << " [";
|
||||
print_bits(lo);
|
||||
print_bits(out, lo);
|
||||
out << ", ";
|
||||
print_bits(hi);
|
||||
print_bits(out, hi);
|
||||
out << "[";
|
||||
}
|
||||
out << std::dec;
|
||||
return out;
|
||||
}
|
||||
|
||||
// TODO move:
|
||||
void set_bit(unsigned i, bool v) { set(m_bits, i, v); }
|
||||
bool well_formed() const {
|
||||
return !has_overflow(m_bits) && (!has_range() || in_range(m_bits));
|
||||
}
|
||||
|
||||
private:
|
||||
static digit_t get_pos_mask(unsigned bit_idx) {
|
||||
return (digit_t)1 << (digit_t)(bit_idx % (8 * sizeof(digit_t)));
|
||||
}
|
||||
|
||||
static digit_t get_bit_word(svector<digit_t> const& bits, unsigned bit_idx) {
|
||||
return bits[bit_idx / (8 * sizeof(digit_t))];
|
||||
}
|
||||
|
||||
static digit_t& get_bit_word(svector<digit_t>& bits, unsigned bit_idx) {
|
||||
return bits[bit_idx / (8 * sizeof(digit_t))];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class sls_pre_valuation : public sls_valuation {
|
||||
public:
|
||||
sls_pre_valuation(unsigned bw):sls_valuation(bw) {}
|
||||
svector<digit_t>& bits() { return m_bits; }
|
||||
bvect& bits() { return m_bits; }
|
||||
void set_bit(unsigned i, bool v) { set(m_bits, i, v); }
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue