#pragma once
#include "math/dd/dd_bdd.h"
#include "util/vector.h"
#include "util/rational.h"
namespace dd {
enum class find_t { empty, singleton, multiple };
std::ostream& operator<<(std::ostream& out, find_t x);
class fdd {
unsigned_vector m_pos2var; unsigned_vector m_var2pos; bdd_manager* m;
bddv m_var;
static unsigned_vector seq(unsigned count, unsigned start = 0, unsigned step = 1) {
unsigned_vector result;
unsigned k = start;
for (unsigned i = 0; i < count; ++i, k += step)
result.push_back(k);
return result;
}
unsigned var2pos(unsigned var) const;
bool contains(bdd const& b, bool_vector const& value) const;
rational bits2rational(bool_vector const& v) const;
bool_vector rational2bits(rational const& r) const;
public:
fdd(bdd_manager& manager, unsigned num_bits, unsigned start = 0, unsigned step = 1) : fdd(manager, seq(num_bits, start, step)) { }
fdd(bdd_manager& manager, unsigned_vector const& vars) : fdd(manager, unsigned_vector(vars)) { }
fdd(bdd_manager& manager, unsigned_vector&& vars);
unsigned num_bits() const { return m_pos2var.size(); }
unsigned_vector const& bdd_vars() const { return m_pos2var; }
bddv const& var() const { return m_var; }
bdd non_zero() const;
bool contains(bdd b, rational const& val) const;
find_t find(bdd b, rational& out_val) const;
find_t find_hint(bdd b, rational const& hint, rational& out_val) const;
bool sup(bdd const& b, bool_vector& lo) const;
bool inf(bdd const& b, bool_vector& hi) const;
bool sup(bdd const& b, rational& lo) const;
bool inf(bdd const& b, rational& hi) const;
rational max(bdd b) const;
rational min(bdd b) const;
};
}