3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-07 18:05:21 +00:00
z3/lib/ext_numeral.h
Leonardo de Moura e9eab22e5c Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:35:25 -07:00

336 lines
8.6 KiB
C++

/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
ext_numeral.h
Abstract:
Goodies for handling extended numerals such as R union { -oo, +oo }.
We can have extended sets of mpq, mpz, mpbq, mpf, etc.
Author:
Leonardo de Moura (leonardo) 2011-12-04.
Revision History:
--*/
#ifndef _EXT_NUMERAL_H_
#define _EXT_NUMERAL_H_
#include<iostream>
#include"debug.h"
enum ext_numeral_kind { EN_MINUS_INFINITY, EN_NUMERAL, EN_PLUS_INFINITY };
template<typename numeral_manager>
bool is_zero(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak) {
return ak == EN_NUMERAL && m.is_zero(a);
}
template<typename numeral_manager>
bool is_pos(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak) {
return ak == EN_PLUS_INFINITY || (ak == EN_NUMERAL && m.is_pos(a));
}
template<typename numeral_manager>
bool is_neg(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak) {
return ak == EN_MINUS_INFINITY || (ak == EN_NUMERAL && m.is_neg(a));
}
inline bool is_infinite(ext_numeral_kind ak) { return ak != EN_NUMERAL; }
template<typename numeral_manager>
void set(numeral_manager & m,
typename numeral_manager::numeral & a,
ext_numeral_kind & ak,
typename numeral_manager::numeral const & b,
ext_numeral_kind bk) {
m.set(a, b);
ak = bk;
}
template<typename numeral_manager>
void reset(numeral_manager & m,
typename numeral_manager::numeral & a,
ext_numeral_kind & ak) {
m.reset(a);
ak = EN_NUMERAL;
}
template<typename numeral_manager>
void neg(numeral_manager & m,
typename numeral_manager::numeral & a,
ext_numeral_kind & ak) {
switch (ak) {
case EN_MINUS_INFINITY:
ak = EN_PLUS_INFINITY;
break;
case EN_NUMERAL:
m.neg(a);
break;
case EN_PLUS_INFINITY:
ak = EN_MINUS_INFINITY;
break;
}
}
template<typename numeral_manager>
void inv(numeral_manager & m,
typename numeral_manager::numeral & a,
ext_numeral_kind & ak) {
SASSERT(numeral_manager::field());
switch (ak) {
case EN_MINUS_INFINITY:
ak = EN_NUMERAL;
m.reset(a);
break;
case EN_NUMERAL:
SASSERT(!m.is_zero(a));
m.inv(a);
break;
case EN_PLUS_INFINITY:
ak = EN_NUMERAL;
m.reset(a);
break;
}
}
template<typename numeral_manager>
void add(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak,
typename numeral_manager::numeral const & b,
ext_numeral_kind bk,
typename numeral_manager::numeral & c,
ext_numeral_kind & ck) {
SASSERT(!(ak == EN_MINUS_INFINITY && bk == EN_PLUS_INFINITY)); // result is undefined
SASSERT(!(ak == EN_PLUS_INFINITY && bk == EN_MINUS_INFINITY)); // result is undefined
if (ak != EN_NUMERAL) {
m.reset(c);
ck = ak;
}
else if (bk != EN_NUMERAL) {
m.reset(c);
ck = bk;
}
else {
m.add(a, b, c);
ck = EN_NUMERAL;
}
}
template<typename numeral_manager>
void sub(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak,
typename numeral_manager::numeral const & b,
ext_numeral_kind bk,
typename numeral_manager::numeral & c,
ext_numeral_kind & ck) {
SASSERT(!(ak == EN_MINUS_INFINITY && bk == EN_MINUS_INFINITY)); // result is undefined
SASSERT(!(ak == EN_PLUS_INFINITY && bk == EN_PLUS_INFINITY)); // result is undefined
if (ak != EN_NUMERAL) {
SASSERT(bk != ak);
m.reset(c);
ck = ak;
}
else {
switch (bk) {
case EN_MINUS_INFINITY:
m.reset(c);
ck = EN_PLUS_INFINITY;
break;
case EN_NUMERAL:
m.sub(a, b, c);
ck = EN_NUMERAL;
break;
case EN_PLUS_INFINITY:
m.reset(c);
ck = EN_MINUS_INFINITY;
break;
}
}
}
template<typename numeral_manager>
void mul(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak,
typename numeral_manager::numeral const & b,
ext_numeral_kind bk,
typename numeral_manager::numeral & c,
ext_numeral_kind & ck) {
if (is_zero(m, a, ak) || is_zero(m, b, bk)) {
m.reset(c);
ck = EN_NUMERAL;
}
else if (is_infinite(ak) || is_infinite(bk)) {
if (is_pos(m, a, ak) == is_pos(m, b, bk))
ck = EN_PLUS_INFINITY;
else
ck = EN_MINUS_INFINITY;
m.reset(c);
}
else {
ck = EN_NUMERAL;
m.mul(a, b, c);
}
}
template<typename numeral_manager>
void div(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak,
typename numeral_manager::numeral const & b,
ext_numeral_kind bk,
typename numeral_manager::numeral & c,
ext_numeral_kind & ck) {
SASSERT(!is_zero(m, b, bk));
if (is_zero(m, a, ak)) {
SASSERT(!is_zero(m, b, bk));
m.reset(c);
ck = EN_NUMERAL;
}
else if (is_infinite(ak)) {
SASSERT(!is_infinite(bk));
if (is_pos(m, a, ak) == is_pos(m, b, bk))
ck = EN_PLUS_INFINITY;
else
ck = EN_MINUS_INFINITY;
m.reset(c);
}
else if (is_infinite(bk)) {
SASSERT(!is_infinite(ak));
m.reset(c);
ck = EN_NUMERAL;
}
else {
ck = EN_NUMERAL;
m.div(a, b, c);
}
}
template<typename numeral_manager>
void power(numeral_manager & m,
typename numeral_manager::numeral & a,
ext_numeral_kind & ak,
unsigned n) {
switch (ak) {
case EN_MINUS_INFINITY:
if (n % 2 == 0)
ak = EN_PLUS_INFINITY;
break;
case EN_NUMERAL:
m.power(a, n, a);
break;
case EN_PLUS_INFINITY:
break; // do nothing
}
}
/**
\brief Return true if (a,ak) == (b,bk).
*/
template<typename numeral_manager>
bool eq(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak,
typename numeral_manager::numeral const & b,
ext_numeral_kind bk) {
if (ak == EN_NUMERAL) {
return bk == EN_NUMERAL && m.eq(a, b);
}
else {
return ak == bk;
}
}
template<typename numeral_manager>
bool neq(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak,
typename numeral_manager::numeral const & b,
ext_numeral_kind bk) {
return !eq(m, a, ak, b, bk);
}
template<typename numeral_manager>
bool lt(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak,
typename numeral_manager::numeral const & b,
ext_numeral_kind bk) {
switch (ak) {
case EN_MINUS_INFINITY:
return bk != EN_MINUS_INFINITY;
case EN_NUMERAL:
switch (bk) {
case EN_MINUS_INFINITY:
return false;
case EN_NUMERAL:
return m.lt(a, b);
case EN_PLUS_INFINITY:
return true;
default:
UNREACHABLE();
return false;
}
case EN_PLUS_INFINITY:
return false;
default:
UNREACHABLE();
return false;
}
}
template<typename numeral_manager>
bool gt(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak,
typename numeral_manager::numeral const & b,
ext_numeral_kind bk) {
return lt(m, b, bk, a, ak);
}
template<typename numeral_manager>
bool le(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak,
typename numeral_manager::numeral const & b,
ext_numeral_kind bk) {
return !gt(m, a, ak, b, bk);
}
template<typename numeral_manager>
bool ge(numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak,
typename numeral_manager::numeral const & b,
ext_numeral_kind bk) {
return !lt(m, a, ak, b, bk);
}
template<typename numeral_manager>
void display(std::ostream & out,
numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak) {
switch (ak) {
case EN_MINUS_INFINITY: out << "-oo"; break;
case EN_NUMERAL: m.display(out, a); break;
case EN_PLUS_INFINITY: out << "+oo"; break;
}
}
#endif