use std::fmt::Debug;
use std::fmt::Display;
use std::ops::{Add, AddAssign, Mul, MulAssign};
pub trait Semiring:
Clone + PartialEq + Debug + Default + Add + AddAssign + Mul + MulAssign + Display
{
type Type: Display;
fn plus(&self, rhs: &Self) -> Self;
fn times(&self, rhs: &Self) -> Self;
fn zero() -> Self;
fn one() -> Self;
fn value(&self) -> Self::Type;
fn set_value(&mut self, Self::Type);
}
pub trait WeaklyDivisibleSemiring: Semiring {
fn inverse(&self) -> Self;
fn divide(&self, rhs: &Self) -> Self;
}
pub trait CompleteSemiring: Semiring {}
pub trait StarSemiring: Semiring {
fn closure(&self) -> Self;
}
macro_rules! add_mul_semiring {
($semiring:ty) => {
impl Add for $semiring {
type Output = $semiring;
fn add(self, other: $semiring) -> $semiring {
self.plus(&other)
}
}
impl AddAssign for $semiring {
fn add_assign(&mut self, other: $semiring) {
let new_value = self.plus(&other).value();
self.set_value(new_value);
}
}
impl Mul for $semiring {
type Output = $semiring;
fn mul(self, other: $semiring) -> $semiring {
self.times(&other)
}
}
impl MulAssign for $semiring {
fn mul_assign(&mut self, other: $semiring) {
let new_value = self.times(&other).value();
self.set_value(new_value)
}
}
};
}
macro_rules! display_semiring {
($semiring:tt) => {
use std::fmt;
impl fmt::Display for $semiring {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value());
Ok(())
}
}
};
}