3
0
Fork 0
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:
Christoph M. Wintersteiger 2023-11-23 16:54:23 +00:00 committed by GitHub
parent 9382b96a32
commit 16753e43f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 845 additions and 117 deletions

View file

@ -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) {

View file

@ -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;