use crate::Context;
use crate::ast::{Ast, Real};
use std::convert::TryFrom;
use z3_sys::*;
pub struct Algebraic {
pub(crate) ctx: Context,
pub(crate) z3_ast: Z3_ast,
}
impl Algebraic {
pub fn is_value(ast: &impl Ast) -> bool {
unsafe { Z3_algebraic_is_value(ast.get_ctx().z3_ctx.0, ast.get_z3_ast()) }
}
pub fn is_positive(&self) -> bool {
unsafe { Z3_algebraic_is_pos(self.ctx.z3_ctx.0, self.z3_ast) }
}
pub fn is_negative(&self) -> bool {
unsafe { Z3_algebraic_is_neg(self.ctx.z3_ctx.0, self.z3_ast) }
}
pub fn is_zero(&self) -> bool {
unsafe { Z3_algebraic_is_zero(self.ctx.z3_ctx.0, self.z3_ast) }
}
pub fn sign(&self) -> i32 {
unsafe { Z3_algebraic_sign(self.ctx.z3_ctx.0, self.z3_ast) }
}
pub fn add(a: &Algebraic, b: &Algebraic) -> Algebraic {
assert_eq!(a.ctx.z3_ctx, b.ctx.z3_ctx);
unsafe {
Algebraic::wrap(
&a.ctx,
Z3_algebraic_add(a.ctx.z3_ctx.0, a.z3_ast, b.z3_ast).unwrap(),
)
}
}
pub fn sub(a: &Algebraic, b: &Algebraic) -> Algebraic {
assert_eq!(a.ctx.z3_ctx, b.ctx.z3_ctx);
unsafe {
Algebraic::wrap(
&a.ctx,
Z3_algebraic_sub(a.ctx.z3_ctx.0, a.z3_ast, b.z3_ast).unwrap(),
)
}
}
pub fn mul(a: &Algebraic, b: &Algebraic) -> Algebraic {
assert_eq!(a.ctx.z3_ctx, b.ctx.z3_ctx);
unsafe {
Algebraic::wrap(
&a.ctx,
Z3_algebraic_mul(a.ctx.z3_ctx.0, a.z3_ast, b.z3_ast).unwrap(),
)
}
}
pub fn div(a: &Algebraic, b: &Algebraic) -> Algebraic {
assert_eq!(a.ctx.z3_ctx, b.ctx.z3_ctx);
unsafe {
Algebraic::wrap(
&a.ctx,
Z3_algebraic_div(a.ctx.z3_ctx.0, a.z3_ast, b.z3_ast).unwrap(),
)
}
}
pub fn root(&self, k: u32) -> Algebraic {
unsafe {
Algebraic::wrap(
&self.ctx,
Z3_algebraic_root(self.ctx.z3_ctx.0, self.z3_ast, k).unwrap(),
)
}
}
pub fn power(&self, k: u32) -> Algebraic {
unsafe {
Algebraic::wrap(
&self.ctx,
Z3_algebraic_power(self.ctx.z3_ctx.0, self.z3_ast, k).unwrap(),
)
}
}
pub fn lt(a: &Algebraic, b: &Algebraic) -> bool {
assert_eq!(a.ctx.z3_ctx, b.ctx.z3_ctx);
unsafe { Z3_algebraic_lt(a.ctx.z3_ctx.0, a.z3_ast, b.z3_ast) }
}
pub fn gt(a: &Algebraic, b: &Algebraic) -> bool {
assert_eq!(a.ctx.z3_ctx, b.ctx.z3_ctx);
unsafe { Z3_algebraic_gt(a.ctx.z3_ctx.0, a.z3_ast, b.z3_ast) }
}
pub fn eq_algebraic(a: &Algebraic, b: &Algebraic) -> bool {
assert_eq!(a.ctx.z3_ctx, b.ctx.z3_ctx);
unsafe { Z3_algebraic_eq(a.ctx.z3_ctx.0, a.z3_ast, b.z3_ast) }
}
}
impl From<Algebraic> for Real {
fn from(a: Algebraic) -> Real {
unsafe { Real::wrap(&a.ctx, a.z3_ast) }
}
}
impl TryFrom<Real> for Algebraic {
type Error = ();
fn try_from(real: Real) -> Result<Self, ()> {
if Algebraic::is_value(&real) {
Ok(unsafe { Algebraic::wrap(&real.ctx, real.z3_ast) })
} else {
Err(())
}
}
}