#pragma once
#include "util/mpq.h"
#include "util/params.h"
#include "util/scoped_numeral.h"
#include "util/scoped_numeral_vector.h"
#include "math/interval/interval.h"
#include "util/z3_exception.h"
#include "util/rlimit.h"
namespace realclosure {
class num;
typedef interval_manager<im_default_config> mpqi_manager;
typedef default_exception exception;
class mk_interval {
public:
virtual ~mk_interval() = default;
virtual void operator()(unsigned k, mpqi_manager & im, mpqi_manager::interval & r) = 0;
};
class manager {
public:
struct imp;
private:
friend class save_interval_ctx;
imp * m_imp;
public:
manager(reslimit& lim, unsynch_mpq_manager & m, params_ref const & p = params_ref(), small_object_allocator * a = nullptr);
~manager();
typedef num numeral;
typedef svector<numeral> numeral_vector;
typedef _scoped_numeral<manager> scoped_numeral;
typedef _scoped_numeral_vector<manager> scoped_numeral_vector;
static void get_param_descrs(param_descrs & r);
static void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
void updt_params(params_ref const & p);
unsynch_mpq_manager & qm() const;
void del(numeral & a);
void mk_infinitesimal(char const * name, char const * pp_name, numeral & r);
void mk_infinitesimal(numeral & r);
void mk_transcendental(char const * name, char const * pp_name, mk_interval & proc, numeral & r);
void mk_transcendental(mk_interval & proc, numeral & r);
void mk_pi(numeral & r);
void mk_e(numeral & r);
void isolate_roots(unsigned n, numeral const * as, numeral_vector & roots);
void reset(numeral & a);
int sign(numeral const & a);
bool is_zero(numeral const & a);
bool is_pos(numeral const & a);
bool is_neg(numeral const & a);
bool is_int(numeral const & a);
bool is_rational(numeral const & a);
bool is_algebraic(numeral const & a);
bool is_infinitesimal(numeral const & a);
bool is_transcendental(numeral const & a);
bool depends_on_infinitesimals(numeral const & a);
void set(numeral & a, int n);
void set(numeral & a, mpz const & n);
void set(numeral & a, mpq const & n);
void set(numeral & a, numeral const & n);
void swap(numeral & a, numeral & b) noexcept;
void root(numeral const & a, unsigned k, numeral & b);
void power(numeral const & a, unsigned k, numeral & b);
void add(numeral const & a, numeral const & b, numeral & c);
void add(numeral const & a, mpz const & b, numeral & c);
void sub(numeral const & a, numeral const & b, numeral & c);
void mul(numeral const & a, numeral const & b, numeral & c);
void neg(numeral & a);
void neg(numeral const & a, numeral & b);
void inv(numeral & a);
void inv(numeral const & a, numeral & b);
void div(numeral const & a, numeral const & b, numeral & c);
int compare(numeral const & a, numeral const & b);
bool eq(numeral const & a, numeral const & b);
bool eq(numeral const & a, mpq const & b);
bool eq(numeral const & a, mpz const & b);
bool neq(numeral const & a, numeral const & b) { return !eq(a, b); }
bool neq(numeral const & a, mpq const & b) { return !eq(a, b); }
bool neq(numeral const & a, mpz const & b) { return !eq(a, b); }
bool lt(numeral const & a, numeral const & b);
bool lt(numeral const & a, mpq const & b);
bool lt(numeral const & a, mpz const & b);
bool gt(numeral const & a, numeral const & b) { return lt(b, a); }
bool gt(numeral const & a, mpq const & b);
bool gt(numeral const & a, mpz const & b);
bool le(numeral const & a, numeral const & b) { return !gt(a, b); }
bool le(numeral const & a, mpq const & b) { return !gt(a, b); }
bool le(numeral const & a, mpz const & b) { return !gt(a, b); }
bool ge(numeral const & a, numeral const & b) { return !lt(a, b); }
bool ge(numeral const & a, mpq const & b) { return !lt(a, b); }
bool ge(numeral const & a, mpz const & b) { return !lt(a, b); }
void display(std::ostream & out, numeral const & a, bool compact=false, bool pp=false) const;
void display_decimal(std::ostream & out, numeral const & a, unsigned precision = 10) const;
void display_interval(std::ostream & out, numeral const & a) const;
void clean_denominators(numeral const & a, numeral & p, numeral & q);
unsigned extension_index(numeral const & a);
symbol transcendental_name(numeral const &a);
symbol infinitesimal_name(numeral const &a);
unsigned num_coefficients(numeral const &a);
numeral get_coefficient(numeral const &a, unsigned i);
unsigned num_sign_conditions(numeral const &a);
int get_sign_condition_sign(numeral const &a, unsigned i);
bool get_interval(numeral const & a, bool & lower_is_inf, bool & lower_is_open, numeral & lower, bool & upper_is_inf, bool & upper_is_open, numeral & upper);
unsigned num_sign_condition_coefficients(numeral const &a, unsigned i);
numeral get_sign_condition_coefficient(numeral const &a, unsigned i, unsigned j);
};
struct value;
class num {
friend class manager;
friend struct manager::imp;
value * m_value;
public:
num():m_value(nullptr) {}
void * data() { return m_value; }
static num mk(void * ptr) { num r; r.m_value = reinterpret_cast<value*>(ptr); return r; }
};
};
typedef realclosure::manager rcmanager;
typedef rcmanager::numeral rcnumeral;
typedef rcmanager::numeral_vector rcnumeral_vector;
typedef rcmanager::scoped_numeral scoped_rcnumeral;
typedef rcmanager::scoped_numeral_vector scoped_rcnumeral_vector;
#define RCF_MK_COMPARISON_CORE(EXTERNAL, INTERNAL, TYPE) \
inline bool EXTERNAL(scoped_rcnumeral const & a, TYPE const & b) { \
rcmanager & m = a.m(); \
scoped_rcnumeral _b(m); \
m.set(_b, b); \
return m.INTERNAL(a, _b); \
}
#define RCF_MK_COMPARISON(EXTERNAL, INTERNAL) \
RCF_MK_COMPARISON_CORE(EXTERNAL, INTERNAL, int) \
RCF_MK_COMPARISON_CORE(EXTERNAL, INTERNAL, mpz) \
RCF_MK_COMPARISON_CORE(EXTERNAL, INTERNAL, mpq)
RCF_MK_COMPARISON(operator==, eq);
RCF_MK_COMPARISON(operator!=, neq);
RCF_MK_COMPARISON(operator<, lt);
RCF_MK_COMPARISON(operator<=, le);
RCF_MK_COMPARISON(operator>, gt);
RCF_MK_COMPARISON(operator>=, ge);
#undef RCF_MK_COMPARISON
#undef RCF_MK_COMPARISON_CORE
#define RCF_MK_BINARY_CORE(EXTERNAL, INTERNAL, TYPE) \
inline scoped_rcnumeral EXTERNAL(scoped_rcnumeral const & a, TYPE const & b) { \
rcmanager & m = a.m(); \
scoped_rcnumeral _b(m); \
m.set(_b, b); \
scoped_rcnumeral r(m); \
m.INTERNAL(a, _b, r); \
return r; \
}
#define RCF_MK_BINARY(EXTERNAL, INTERNAL) \
RCF_MK_BINARY_CORE(EXTERNAL, INTERNAL, int) \
RCF_MK_BINARY_CORE(EXTERNAL, INTERNAL, mpz) \
RCF_MK_BINARY_CORE(EXTERNAL, INTERNAL, mpq)
RCF_MK_BINARY(operator+, add)
RCF_MK_BINARY(operator-, sub)
RCF_MK_BINARY(operator*, mul)
RCF_MK_BINARY(operator/, div)
#undef RCF_MK_BINARY
#undef RCF_MK_BINARY_CORE
inline scoped_rcnumeral root(scoped_rcnumeral const & a, unsigned k) {
scoped_rcnumeral r(a.m());
a.m().root(a, k, r);
return r;
}
inline scoped_rcnumeral power(scoped_rcnumeral const & a, unsigned k) {
scoped_rcnumeral r(a.m());
a.m().power(a, k, r);
return r;
}
inline scoped_rcnumeral operator^(scoped_rcnumeral const & a, unsigned k) {
return power(a, k);
}
inline bool is_int(scoped_rcnumeral const & a) {
return a.m().is_int(a);
}
struct rc_sym_pp {
rcmanager & m;
rcnumeral const & n;
rc_sym_pp(rcmanager & _m, rcnumeral const & _n):m(_m), n(_n) {}
rc_sym_pp(scoped_rcnumeral const & _n):m(_n.m()), n(_n.get()) {}
};
inline rc_sym_pp sym_pp(scoped_rcnumeral const & _n) {
return rc_sym_pp(_n);
}
inline std::ostream & operator<<(std::ostream & out, rc_sym_pp const & n) {
n.m.display(out, n.n);
return out;
}
struct rc_decimal_pp {
rcmanager & m;
rcnumeral const & n;
unsigned prec;
rc_decimal_pp(rcmanager & _m, rcnumeral const & _n, unsigned p):m(_m), n(_n), prec(p) {}
rc_decimal_pp(scoped_rcnumeral const & _n, unsigned p):m(_n.m()), n(_n.get()), prec(p) {}
};
inline std::ostream & operator<<(std::ostream & out, rc_decimal_pp const & n) {
n.m.display_decimal(out, n.n, n.prec);
return out;
}
inline rc_decimal_pp decimal_pp(scoped_rcnumeral const & n, unsigned prec = 10) {
return rc_decimal_pp(n, prec);
}
struct rc_interval_pp {
rcmanager & m;
rcnumeral const & n;
rc_interval_pp(rcmanager & _m, rcnumeral const & _n):m(_m), n(_n) {}
rc_interval_pp(scoped_rcnumeral const & _n):m(_n.m()), n(_n.get()) {}
};
inline std::ostream & operator<<(std::ostream & out, rc_interval_pp const & n) {
n.m.display_interval(out, n.n);
return out;
}
inline rc_interval_pp interval_pp(scoped_rcnumeral const & n) {
return rc_interval_pp(n);
}