use crate::{
algebra::PartialOrder,
time::{Antichain, AntichainRef},
};
use std::{
cmp::{max, min},
time::Duration,
};
pub trait Lattice: PartialOrder {
fn join(&self, other: &Self) -> Self;
#[inline]
fn join_assign(&mut self, other: &Self)
where
Self: Sized,
{
*self = self.join(other);
}
fn meet(&self, other: &Self) -> Self;
#[inline]
fn meet_assign(&mut self, other: &Self)
where
Self: Sized,
{
*self = self.meet(other);
}
#[inline]
fn advance_by(&mut self, frontier: AntichainRef<Self>)
where
Self: Sized,
{
let mut iter = frontier.iter();
if let Some(first) = iter.next() {
let mut result = self.join(first);
for f in iter {
result.meet_assign(&self.join(f));
}
*self = result;
}
}
}
macro_rules! implement_lattice {
($index_type:ty, $minimum:expr_2021) => {
impl Lattice for $index_type {
#[inline]
fn join(&self, other: &Self) -> Self {
max(*self, *other)
}
#[inline]
fn meet(&self, other: &Self) -> Self {
min(*self, *other)
}
}
};
}
implement_lattice!(Duration, Duration::new(0, 0));
implement_lattice!(usize, 0);
implement_lattice!(u128, 0);
implement_lattice!(u64, 0);
implement_lattice!(u32, 0);
implement_lattice!(u16, 0);
implement_lattice!(u8, 0);
implement_lattice!(isize, 0);
implement_lattice!(i128, 0);
implement_lattice!(i64, 0);
implement_lattice!(i32, 0);
implement_lattice!(i16, 0);
implement_lattice!(i8, 0);
implement_lattice!((), ());
impl<T> Lattice for Antichain<T>
where
T: Lattice + Clone,
{
#[inline]
fn join(&self, other: &Self) -> Self {
let mut upper = Antichain::new();
for time1 in self {
for time2 in other {
upper.insert(time1.join(time2));
}
}
upper
}
#[inline]
fn meet(&self, other: &Self) -> Self {
let mut upper = Antichain::new();
for time1 in self {
upper.insert(time1.clone());
}
for time2 in other {
upper.insert(time2.clone());
}
upper
}
}
impl<T> AntichainRef<'_, T>
where
T: Lattice + Clone,
{
#[inline]
pub fn join(self, other: Self) -> Antichain<T> {
let mut upper = Antichain::new();
for time1 in self {
for time2 in other {
upper.insert(time1.join(time2));
}
}
upper
}
#[inline]
pub fn meet(self, other: Self) -> Antichain<T> {
let mut upper = Antichain::new();
for time1 in self {
upper.insert(time1.clone());
}
for time2 in other {
upper.insert(time2.clone());
}
upper
}
}