pub mod reader;
pub mod writer;
use std::fmt::Display;
use std::num::NonZero;
use std::ops::Add;
use std::ops::Mul;
use std::ops::Not;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum IntComparison {
GreaterEqual,
LessEqual,
Equal,
NotEqual,
}
impl Display for IntComparison {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
IntComparison::GreaterEqual => ">=",
IntComparison::LessEqual => "<=",
IntComparison::Equal => "==",
IntComparison::NotEqual => "!=",
};
write!(f, "{s}")
}
}
pub trait IntValue: Clone + Display + Ord + Mul<Output = Self> + Add<Output = Self> {
fn increment(&self) -> Self;
fn decrement(&self) -> Self;
fn shift_left(&self) -> Self;
fn from_digit(byte: u8) -> Self;
}
pub trait SignedIntValue: IntValue {
fn negate(&self) -> Self;
}
macro_rules! impl_int_value {
($type:ty) => {
impl IntValue for $type {
#[inline]
fn increment(&self) -> Self {
(*self) + 1
}
#[inline]
fn decrement(&self) -> Self {
(*self) - 1
}
#[inline]
fn shift_left(&self) -> Self {
(*self) * 10
}
#[allow(trivial_numeric_casts, reason = "inside macro")]
#[inline]
fn from_digit(byte: u8) -> Self {
assert!(byte.is_ascii_digit());
(byte - b'0') as Self
}
}
};
}
macro_rules! impl_signed_int_value {
($type:ty) => {
impl SignedIntValue for $type {
#[inline]
fn negate(&self) -> Self {
(*self) * -1
}
}
};
}
impl_int_value!(u8);
impl_int_value!(u16);
impl_int_value!(u32);
impl_int_value!(u64);
impl_int_value!(i8);
impl_int_value!(i16);
impl_int_value!(i32);
impl_int_value!(i64);
impl_signed_int_value!(i8);
impl_signed_int_value!(i16);
impl_signed_int_value!(i32);
impl_signed_int_value!(i64);
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct IntAtomic<Identifier, Int> {
pub name: Identifier,
pub comparison: IntComparison,
pub value: Int,
}
impl<Identifier, Int> IntAtomic<Identifier, Int> {
pub fn new(name: Identifier, comparison: IntComparison, value: Int) -> Self {
IntAtomic {
name,
comparison,
value,
}
}
}
impl<Identifier: Display, Int: Display> Display for IntAtomic<Identifier, Int> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let IntAtomic {
name,
comparison,
value,
} = self;
write!(f, "[{name} {comparison} {value}]")
}
}
impl<Identifier, Int> Not for IntAtomic<Identifier, Int>
where
Int: IntValue,
{
type Output = Self;
fn not(self) -> Self::Output {
IntAtomic {
name: self.name,
comparison: match self.comparison {
IntComparison::GreaterEqual => IntComparison::LessEqual,
IntComparison::LessEqual => IntComparison::GreaterEqual,
IntComparison::Equal => IntComparison::NotEqual,
IntComparison::NotEqual => IntComparison::Equal,
},
value: match self.comparison {
IntComparison::GreaterEqual => self.value.decrement(),
IntComparison::LessEqual => self.value.increment(),
IntComparison::Equal | IntComparison::NotEqual => self.value,
},
}
}
}
pub type ConstraintId = NonZero<u32>;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Inference<Identifier, Int, Label> {
pub constraint_id: ConstraintId,
pub premises: Vec<IntAtomic<Identifier, Int>>,
pub consequent: Option<IntAtomic<Identifier, Int>>,
pub generated_by: Option<ConstraintId>,
pub label: Option<Label>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Deduction<Identifier, Int> {
pub constraint_id: ConstraintId,
pub premises: Vec<IntAtomic<Identifier, Int>>,
pub sequence: Vec<ConstraintId>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Conclusion<Identifier, Int> {
Unsat,
DualBound(IntAtomic<Identifier, Int>),
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Step<Identifier, Int, Label> {
Inference(Inference<Identifier, Int, Label>),
Deduction(Deduction<Identifier, Int>),
Conclusion(Conclusion<Identifier, Int>),
}