use crate::kernel::domain::Domain;
use std::fmt;
use std::hash::{Hash, Hasher};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ExprId(pub(crate) u32);
#[derive(Debug, Clone)]
pub struct BigInt(pub rug::Integer);
impl PartialEq for BigInt {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Eq for BigInt {}
impl Hash for BigInt {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.to_string_radix(16).hash(state);
}
}
impl fmt::Display for BigInt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone)]
pub struct BigRat(pub rug::Rational);
impl PartialEq for BigRat {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Eq for BigRat {}
impl Hash for BigRat {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.numer().to_string_radix(16).hash(state);
self.0.denom().to_string_radix(16).hash(state);
}
}
impl fmt::Display for BigRat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if *self.0.denom() == 1 {
write!(f, "{}", self.0.numer())
} else {
write!(f, "{}/{}", self.0.numer(), self.0.denom())
}
}
}
#[derive(Debug, Clone)]
pub struct BigFloat {
pub inner: rug::Float,
pub prec: u32,
}
impl PartialEq for BigFloat {
fn eq(&self, other: &Self) -> bool {
if self.prec != other.prec {
return false;
}
match (self.inner.is_nan(), other.inner.is_nan()) {
(true, true) => true,
(false, false) => self.inner == other.inner,
_ => false,
}
}
}
impl Eq for BigFloat {}
impl Hash for BigFloat {
fn hash<H: Hasher>(&self, state: &mut H) {
self.prec.hash(state);
if self.inner.is_nan() {
"nan".hash(state);
} else {
self.inner.to_string_radix(16, None).hash(state);
}
}
}
impl fmt::Display for BigFloat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.inner)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum PredicateKind {
Lt,
Le,
Gt,
Ge,
Eq,
Ne,
And,
Or,
Not,
True,
False,
}
impl fmt::Display for PredicateKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
PredicateKind::Lt => "<",
PredicateKind::Le => "≤",
PredicateKind::Gt => ">",
PredicateKind::Ge => "≥",
PredicateKind::Eq => "=",
PredicateKind::Ne => "≠",
PredicateKind::And => "∧",
PredicateKind::Or => "∨",
PredicateKind::Not => "¬",
PredicateKind::True => "True",
PredicateKind::False => "False",
};
write!(f, "{s}")
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ExprData {
Symbol {
name: String,
domain: Domain,
commutative: bool,
},
Integer(BigInt),
Rational(BigRat),
Float(BigFloat),
Add(Vec<ExprId>),
Mul(Vec<ExprId>),
Pow {
base: ExprId,
exp: ExprId,
},
Func {
name: String,
args: Vec<ExprId>,
},
Piecewise {
branches: Vec<(ExprId /* cond */, ExprId /* value */)>,
default: ExprId,
},
Predicate {
kind: PredicateKind,
args: Vec<ExprId>,
},
Forall {
var: ExprId,
body: ExprId,
},
Exists {
var: ExprId,
body: ExprId,
},
BigO(ExprId),
}