mirror of
https://github.com/Z3Prover/z3
synced 2025-08-04 02:10:23 +00:00
Add accessors for RCF numeral internals (#7013)
This commit is contained in:
parent
9382b96a32
commit
16753e43f1
7 changed files with 845 additions and 117 deletions
|
@ -2498,6 +2498,35 @@ namespace realclosure {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if a is an algebraic number.
|
||||
*/
|
||||
bool is_algebraic(numeral const & a) {
|
||||
return is_rational_function(a) && to_rational_function(a)->ext()->is_algebraic();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if a represents an infinitesimal.
|
||||
*/
|
||||
bool is_infinitesimal(numeral const & a) {
|
||||
return is_rational_function(a) && to_rational_function(a)->ext()->is_infinitesimal();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if a is a transcendental.
|
||||
*/
|
||||
bool is_transcendental(numeral const & a) {
|
||||
return is_rational_function(a) && to_rational_function(a)->ext()->is_transcendental();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if a is a rational.
|
||||
*/
|
||||
bool is_rational(numeral const & a) {
|
||||
return a.m_value->is_rational();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Return true if a depends on infinitesimal extensions.
|
||||
*/
|
||||
|
@ -3330,6 +3359,151 @@ namespace realclosure {
|
|||
set(q, _q);
|
||||
}
|
||||
|
||||
unsigned extension_index(numeral const & a) {
|
||||
if (!is_rational_function(a))
|
||||
return -1;
|
||||
return to_rational_function(a)->ext()->idx();
|
||||
}
|
||||
|
||||
symbol transcendental_name(numeral const & a) {
|
||||
if (!is_transcendental(a))
|
||||
return symbol();
|
||||
return to_transcendental(to_rational_function(a)->ext())->m_name;
|
||||
}
|
||||
|
||||
symbol infinitesimal_name(numeral const & a) {
|
||||
if (!is_infinitesimal(a))
|
||||
return symbol();
|
||||
return to_infinitesimal(to_rational_function(a)->ext())->m_name;
|
||||
}
|
||||
|
||||
unsigned num_coefficients(numeral const & a) {
|
||||
if (!is_algebraic(a))
|
||||
return 0;
|
||||
return to_algebraic(to_rational_function(a)->ext())->p().size();
|
||||
}
|
||||
|
||||
numeral get_coefficient(numeral const & a, unsigned i)
|
||||
{
|
||||
if (!is_algebraic(a))
|
||||
return numeral();
|
||||
algebraic * ext = to_algebraic(to_rational_function(a)->ext());
|
||||
if (i >= ext->p().size())
|
||||
return numeral();
|
||||
value_ref v(*this);
|
||||
v = ext->p()[i];
|
||||
numeral r;
|
||||
set(r, v);
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned num_sign_conditions(numeral const & a) {
|
||||
unsigned r = 0;
|
||||
if (is_algebraic(a)) {
|
||||
algebraic * ext = to_algebraic(to_rational_function(a)->ext());
|
||||
const sign_det * sdt = ext->sdt();
|
||||
if (sdt) {
|
||||
sign_condition * sc = sdt->sc(ext->sc_idx());
|
||||
while (sc) {
|
||||
r++;
|
||||
sc = sc->prev();
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int get_sign_condition_sign(numeral const & a, unsigned i)
|
||||
{
|
||||
if (!is_algebraic(a))
|
||||
return 0;
|
||||
algebraic * ext = to_algebraic(to_rational_function(a)->ext());
|
||||
const sign_det * sdt = ext->sdt();
|
||||
if (!sdt)
|
||||
return 0;
|
||||
else {
|
||||
sign_condition * sc = sdt->sc(ext->sc_idx());
|
||||
while (i) {
|
||||
if (sc) sc = sc->prev();
|
||||
i--;
|
||||
}
|
||||
return sc ? sc->sign() : 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool get_interval(numeral const & a, int & lower_is_inf, int & lower_is_open, numeral & lower, int & upper_is_inf, int & upper_is_open, numeral & upper)
|
||||
{
|
||||
if (!is_algebraic(a))
|
||||
return false;
|
||||
lower = numeral();
|
||||
upper = numeral();
|
||||
algebraic * ext = to_algebraic(to_rational_function(a)->ext());
|
||||
mpbqi &ivl = ext->iso_interval();
|
||||
lower_is_inf = ivl.lower_is_inf();
|
||||
lower_is_open = ivl.lower_is_open();
|
||||
if (!m_bqm.is_zero(ivl.lower()))
|
||||
set(lower, mk_rational(ivl.lower()));
|
||||
upper_is_inf = ivl.upper_is_inf();
|
||||
upper_is_open = ivl.upper_is_open();
|
||||
if (!m_bqm.is_zero(ivl.upper()))
|
||||
set(upper, mk_rational(ivl.upper()));
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned get_sign_condition_size(numeral const &a, unsigned i) {
|
||||
algebraic * ext = to_algebraic(to_rational_function(a)->ext());
|
||||
const sign_det * sdt = ext->sdt();
|
||||
if (!sdt)
|
||||
return 0;
|
||||
sign_condition * sc = sdt->sc(ext->sc_idx());
|
||||
while (i) {
|
||||
if (sc) sc = sc->prev();
|
||||
i--;
|
||||
}
|
||||
return ext->sdt()->qs()[sc->qidx()].size();
|
||||
}
|
||||
|
||||
int num_sign_condition_coefficients(numeral const &a, unsigned i)
|
||||
{
|
||||
if (!is_algebraic(a))
|
||||
return 0;
|
||||
algebraic * ext = to_algebraic(to_rational_function(a)->ext());
|
||||
const sign_det * sdt = ext->sdt();
|
||||
if (!sdt)
|
||||
return 0;
|
||||
sign_condition * sc = sdt->sc(ext->sc_idx());
|
||||
while (i) {
|
||||
if (sc) sc = sc->prev();
|
||||
i--;
|
||||
}
|
||||
const polynomial & q = ext->sdt()->qs()[sc->qidx()];
|
||||
return q.size();
|
||||
}
|
||||
|
||||
numeral get_sign_condition_coefficient(numeral const &a, unsigned i, unsigned j)
|
||||
{
|
||||
if (!is_algebraic(a))
|
||||
return numeral();
|
||||
algebraic * ext = to_algebraic(to_rational_function(a)->ext());
|
||||
const sign_det * sdt = ext->sdt();
|
||||
if (!sdt)
|
||||
return numeral();
|
||||
sign_condition * sc = sdt->sc(ext->sc_idx());
|
||||
while (i) {
|
||||
if (sc) sc = sc->prev();
|
||||
i--;
|
||||
}
|
||||
const polynomial & q = ext->sdt()->qs()[sc->qidx()];
|
||||
if (j >= q.size())
|
||||
return numeral();
|
||||
value_ref v(*this);
|
||||
v = q[j];
|
||||
numeral r;
|
||||
set(r, v);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------
|
||||
//
|
||||
// GCD of integer coefficients
|
||||
|
@ -6103,6 +6277,22 @@ namespace realclosure {
|
|||
return m_imp->is_int(a);
|
||||
}
|
||||
|
||||
bool manager::is_rational(numeral const & a) {
|
||||
return m_imp->is_rational(a);
|
||||
}
|
||||
|
||||
bool manager::is_algebraic(numeral const & a) {
|
||||
return m_imp->is_algebraic(a);
|
||||
}
|
||||
|
||||
bool manager::is_infinitesimal(numeral const & a) {
|
||||
return m_imp->is_infinitesimal(a);
|
||||
}
|
||||
|
||||
bool manager::is_transcendental(numeral const & a) {
|
||||
return m_imp->is_transcendental(a);
|
||||
}
|
||||
|
||||
bool manager::depends_on_infinitesimals(numeral const & a) {
|
||||
return m_imp->depends_on_infinitesimals(a);
|
||||
}
|
||||
|
@ -6251,6 +6441,56 @@ namespace realclosure {
|
|||
save_interval_ctx ctx(this);
|
||||
m_imp->clean_denominators(a, p, q);
|
||||
}
|
||||
|
||||
unsigned manager::extension_index(numeral const & a)
|
||||
{
|
||||
return m_imp->extension_index(a);
|
||||
}
|
||||
|
||||
symbol manager::transcendental_name(numeral const &a)
|
||||
{
|
||||
return m_imp->transcendental_name(a);
|
||||
}
|
||||
|
||||
symbol manager::infinitesimal_name(numeral const &a)
|
||||
{
|
||||
return m_imp->infinitesimal_name(a);
|
||||
}
|
||||
|
||||
unsigned manager::num_coefficients(numeral const &a)
|
||||
{
|
||||
return m_imp->num_coefficients(a);
|
||||
}
|
||||
|
||||
manager::numeral manager::get_coefficient(numeral const &a, unsigned i)
|
||||
{
|
||||
return m_imp->get_coefficient(a, i);
|
||||
}
|
||||
|
||||
unsigned manager::num_sign_conditions(numeral const &a)
|
||||
{
|
||||
return m_imp->num_sign_conditions(a);
|
||||
}
|
||||
|
||||
int manager::get_sign_condition_sign(numeral const &a, unsigned i)
|
||||
{
|
||||
return m_imp->get_sign_condition_sign(a, i);
|
||||
}
|
||||
|
||||
bool manager::get_interval(numeral const & a, int & lower_is_inf, int & lower_is_open, numeral & lower, int & upper_is_inf, int & upper_is_open, numeral & upper)
|
||||
{
|
||||
return m_imp->get_interval(a, lower_is_inf, lower_is_open, lower, upper_is_inf, upper_is_open, upper);
|
||||
}
|
||||
|
||||
unsigned manager::num_sign_condition_coefficients(numeral const &a, unsigned i)
|
||||
{
|
||||
return m_imp->num_sign_condition_coefficients(a, i);
|
||||
}
|
||||
|
||||
manager::numeral manager::get_sign_condition_coefficient(numeral const &a, unsigned i, unsigned j)
|
||||
{
|
||||
return m_imp->get_sign_condition_coefficient(a, i, j);
|
||||
}
|
||||
};
|
||||
|
||||
void pp(realclosure::manager::imp * imp, realclosure::polynomial const & p, realclosure::extension * ext) {
|
||||
|
|
|
@ -70,14 +70,14 @@ namespace realclosure {
|
|||
*/
|
||||
void mk_infinitesimal(char const * name, char const * pp_name, numeral & r);
|
||||
void mk_infinitesimal(numeral & r);
|
||||
|
||||
|
||||
/**
|
||||
\brief Add a new transcendental real value to the field.
|
||||
\brief Add a new transcendental real value to the field.
|
||||
The functor \c mk_interval is used to compute approximations of the transcendental value.
|
||||
This procedure should be used with care, if the value is not really transcendental with respect to the current
|
||||
field, computations with the new numeral may not terminate.
|
||||
Example: we extended the field with Pi. Pi is transcendental with respect to a field that contains only algebraic real numbers.
|
||||
So, this step is fine. Let us call the resultant field F.
|
||||
So, this step is fine. Let us call the resultant field F.
|
||||
Then, we extend the field F with 1 - Pi. 1 - Pi is transcendental with respect to algebraic real numbers, but it is NOT transcendental
|
||||
with respect to F, since F contains Pi.
|
||||
*/
|
||||
|
@ -109,12 +109,12 @@ namespace realclosure {
|
|||
\brief Return the sign of a.
|
||||
*/
|
||||
int sign(numeral const & a);
|
||||
|
||||
|
||||
/**
|
||||
\brief Return true if a is zero.
|
||||
*/
|
||||
bool is_zero(numeral const & a);
|
||||
|
||||
|
||||
/**
|
||||
\brief Return true if a is positive.
|
||||
*/
|
||||
|
@ -129,13 +129,33 @@ namespace realclosure {
|
|||
\brief Return true if a is an integer.
|
||||
*/
|
||||
bool is_int(numeral const & a);
|
||||
|
||||
|
||||
/**
|
||||
\brief Return true if a is a rational.
|
||||
*/
|
||||
bool is_rational(numeral const & a);
|
||||
|
||||
/**
|
||||
\brief Return true if a is an algebraic number.
|
||||
*/
|
||||
bool is_algebraic(numeral const & a);
|
||||
|
||||
/**
|
||||
\brief Return true if a represents an infinitesimal.
|
||||
*/
|
||||
bool is_infinitesimal(numeral const & a);
|
||||
|
||||
/**
|
||||
\brief Return true if a is a transcendental.
|
||||
*/
|
||||
bool is_transcendental(numeral const & a);
|
||||
|
||||
/**
|
||||
\brief Return true if the representation of \c a depends on
|
||||
infinitesimal extensions.
|
||||
*/
|
||||
bool depends_on_infinitesimals(numeral const & a);
|
||||
|
||||
|
||||
/**
|
||||
\brief a <- n
|
||||
*/
|
||||
|
@ -148,14 +168,14 @@ namespace realclosure {
|
|||
|
||||
/**
|
||||
\brief Return a^{1/k}
|
||||
|
||||
|
||||
Throws an exception if (a is negative and k is even) or (k is zero).
|
||||
*/
|
||||
*/
|
||||
void root(numeral const & a, unsigned k, numeral & b);
|
||||
|
||||
|
||||
/**
|
||||
\brief Return a^k
|
||||
|
||||
|
||||
Throws an exception if 0^0.
|
||||
*/
|
||||
void power(numeral const & a, unsigned k, numeral & b);
|
||||
|
@ -180,7 +200,7 @@ namespace realclosure {
|
|||
\brief a <- -a
|
||||
*/
|
||||
void neg(numeral & a);
|
||||
|
||||
|
||||
/**
|
||||
\brief b <- -a
|
||||
*/
|
||||
|
@ -190,7 +210,7 @@ namespace realclosure {
|
|||
\brief a <- 1/a if a != 0
|
||||
*/
|
||||
void inv(numeral & a);
|
||||
|
||||
|
||||
/**
|
||||
\brief b <- 1/a if a != 0
|
||||
*/
|
||||
|
@ -207,7 +227,7 @@ namespace realclosure {
|
|||
Return 1 if a > b
|
||||
*/
|
||||
int compare(numeral const & a, numeral const & b);
|
||||
|
||||
|
||||
/**
|
||||
\brief a == b
|
||||
*/
|
||||
|
@ -249,7 +269,7 @@ namespace realclosure {
|
|||
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;
|
||||
|
||||
/**
|
||||
|
@ -259,10 +279,30 @@ namespace realclosure {
|
|||
*/
|
||||
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, int & lower_is_inf, int & lower_is_open, numeral & lower, int & upper_is_inf, int & 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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue