z3-z3-4.13.0.src.util.ext_numeral.h Maven / Gradle / Ivy
The newest version!
/*++
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:
--*/
#pragma once
#include
#include "util/debug.h"
enum ext_numeral_kind { EN_MINUS_INFINITY, EN_NUMERAL, EN_PLUS_INFINITY };
template
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
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
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
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
void reset(numeral_manager & m,
typename numeral_manager::numeral & a,
ext_numeral_kind & ak) {
m.reset(a);
ak = EN_NUMERAL;
}
template
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
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
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
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
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
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
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
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
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
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
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
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
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
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;
}
}
template
void display_pp(std::ostream & out,
numeral_manager & m,
typename numeral_manager::numeral const & a,
ext_numeral_kind ak) {
switch (ak) {
case EN_MINUS_INFINITY: out << "-∞"; break;
case EN_NUMERAL: m.display_pp(out, a); break;
case EN_PLUS_INFINITY: out << "+∞"; break;
}
}