z3-z3-4.13.0.src.util.approx_set.h Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
approx_set.h
Abstract:
Approximated sets.
Author:
Leonardo de Moura (leonardo) 2007-03-02.
Revision History:
--*/
#pragma once
#include
#include "util/debug.h"
template class approx_set_traits;
template <> class approx_set_traits {
public:
static const unsigned capacity = 64;
static const unsigned long long zero = 0ull;
static const unsigned long long one = 1ull;
};
static_assert(sizeof(unsigned long long) == 8, "");
template <> class approx_set_traits {
public:
static const unsigned capacity = 32;
static const unsigned zero = 0;
static const unsigned one = 1;
};
static_assert(sizeof(unsigned) == 4, "unsigned are 4 bytes");
template
class approx_set_tpl : private T2U_Proc {
protected:
R m_set = approx_set_traits::zero;
unsigned e2u(T const & e) const { return T2U_Proc::operator()(e); }
R u2s(unsigned u) const { return (approx_set_traits::one << (u & (approx_set_traits::capacity - 1))); }
R e2s(T const & e) const { return u2s(e2u(e)); }
static approx_set_tpl r2s(R const & s) { approx_set_tpl r; r.m_set = s; return r; }
public:
approx_set_tpl() = default;
explicit approx_set_tpl(T const & e):
m_set(e2s(e)) {
}
approx_set_tpl(unsigned sz, T const * es) {
for (unsigned i = 0; i < sz; i++)
insert(es[i]);
}
void set(R s) { m_set = s; }
R get() const { return m_set; }
void insert(T const & e) {
m_set |= e2s(e);
}
bool may_contain(T const & e) const {
return (m_set & e2s(e)) != approx_set_traits::zero;
}
bool must_not_contain(T const & e) const {
return !may_contain(e);
}
friend inline approx_set_tpl mk_union(approx_set_tpl const & s1, approx_set_tpl const & s2) {
return r2s(s1.m_set | s2.m_set);
}
friend inline approx_set_tpl mk_intersection(approx_set_tpl const & s1, approx_set_tpl const & s2) {
return r2s(s1.m_set & s2.m_set);
}
void operator|=(approx_set_tpl const & other) {
m_set |= other.m_set;
}
void operator&=(approx_set_tpl const & other) {
m_set &= other.m_set;
}
void operator-=(approx_set_tpl const & other) {
m_set &= ~(other.m_set);
}
bool empty() const {
return m_set == approx_set_traits::zero;
}
friend inline bool empty(approx_set_tpl const & s) {
return s.empty();
}
bool must_not_subset(approx_set_tpl const & s2) const {
return (m_set & ~(s2.m_set)) != approx_set_traits::zero;
}
friend inline bool must_not_subset(approx_set_tpl const & s1, approx_set_tpl const & s2) {
return s1.must_not_subset(s2);
}
bool must_not_subsume(approx_set_tpl const & s2) const {
return must_not_subset(s2);
}
friend inline bool must_not_subsume(approx_set_tpl const & s1, approx_set_tpl const & s2) {
return s1.must_not_subset(s2);
}
friend inline bool must_not_eq(approx_set_tpl const & s1, approx_set_tpl const & s2) { return s1.m_set != s2.m_set; }
friend inline bool may_eq(approx_set_tpl const & s1, approx_set_tpl const & s2) { return s1.m_set == s2.m_set; }
/**
\brief Return if s1 and s2 are the same approximated set.
*/
bool equiv(approx_set_tpl const & s2) const { return m_set == s2.m_set; }
friend inline bool equiv(approx_set_tpl const & s1, approx_set_tpl const & s2) { return s1.m_set == s2.m_set; }
/**
\brief Return true if the approximation of s1 is a subset of the approximation of s2.
*/
friend inline bool approx_subset(approx_set_tpl const & s1, approx_set_tpl const & s2) {
return s2.equiv(mk_union(s1, s2));
}
void reset() {
m_set = approx_set_traits::zero;
}
bool empty_intersection(approx_set_tpl const & other) const {
return mk_intersection(*this, other).empty();
}
};
struct u2u { unsigned operator()(unsigned u) const { return u; } };
typedef approx_set_tpl u_approx_set;
#define APPROX_SET_CAPACITY (approx_set_traits::capacity)
class approx_set : public u_approx_set {
public:
approx_set() = default;
approx_set(unsigned e):u_approx_set(e) {}
class iterator {
unsigned long long m_set;
unsigned m_val;
void move_to_next() {
// TODO: this code can be optimized in platforms with special
// instructions to count leading (trailing) zeros in a word.
while (m_set > 0) {
if ((m_set & 1ull) != 0) {
return;
}
m_val ++;
m_set = m_set >> 1;
}
}
public:
iterator(unsigned long long s):
m_set(s),
m_val(0) {
move_to_next();
}
unsigned operator*() const {
return m_val;
}
iterator & operator++() {
m_val++;
m_set = m_set >> 1;
move_to_next();
return *this;
}
iterator operator++(int) {
iterator tmp = *this;
++*this;
return tmp;
}
bool operator==(iterator const & it) const {
return m_set == it.m_set;
}
bool operator!=(iterator const & it) const {
return m_set != it.m_set;
}
};
iterator begin() const {
return iterator(m_set);
}
static iterator end() {
return iterator(0);
}
void display(std::ostream & out) const;
unsigned size() const;
// for backward compatibility
friend inline bool operator==(approx_set const & s1, approx_set const & s2) { return may_eq(s1, s2); }
};
inline std::ostream & operator<<(std::ostream & out, approx_set const & s) {
s.display(out);
return out;
}