use timely::order::PartialOrder;
use timely::progress::{Antichain, frontier::AntichainRef};
pub trait Lattice : PartialOrder {
fn join(&self, other: &Self) -> Self;
fn join_assign(&mut self, other: &Self) where Self: Sized {
*self = self.join(other);
}
fn meet(&self, other: &Self) -> Self;
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;
}
}
}
use timely::order::Product;
impl<T1: Lattice, T2: Lattice> Lattice for Product<T1, T2> {
#[inline]
fn join(&self, other: &Product<T1, T2>) -> Product<T1, T2> {
Product {
outer: self.outer.join(&other.outer),
inner: self.inner.join(&other.inner),
}
}
#[inline]
fn meet(&self, other: &Product<T1, T2>) -> Product<T1, T2> {
Product {
outer: self.outer.meet(&other.outer),
inner: self.inner.meet(&other.inner),
}
}
}
pub trait Maximum {
fn maximum() -> Self;
}
macro_rules! implement_maximum {
($($index_type:ty,)*) => (
$(
impl Maximum for $index_type {
fn maximum() -> Self { Self::MAX }
}
)*
)
}
implement_maximum!(usize, u128, u64, u32, u16, u8, isize, i128, i64, i32, i16, i8, Duration,);
impl Maximum for () { fn maximum() -> () { () }}
use timely::progress::Timestamp;
impl<T1: Lattice+Clone, T2: Lattice+Clone+Maximum+Timestamp> Lattice for (T1, T2) {
#[inline]
fn join(&self, other: &(T1, T2)) -> (T1, T2) {
if self.0.eq(&other.0) {
(self.0.clone(), self.1.join(&other.1))
} else if self.0.less_than(&other.0) {
other.clone()
} else if other.0.less_than(&self.0) {
self.clone()
} else {
(self.0.join(&other.0), T2::minimum())
}
}
#[inline]
fn meet(&self, other: &(T1, T2)) -> (T1, T2) {
if self.0.eq(&other.0) {
(self.0.clone(), self.1.meet(&other.1))
} else if self.0.less_than(&other.0) {
self.clone()
} else if other.0.less_than(&self.0) {
other.clone()
} else {
(self.0.meet(&other.0), T2::maximum())
}
}
}
macro_rules! implement_lattice {
($index_type:ty, $minimum:expr) => (
impl Lattice for $index_type {
#[inline] fn join(&self, other: &Self) -> Self { ::std::cmp::max(*self, *other) }
#[inline] fn meet(&self, other: &Self) -> Self { ::std::cmp::min(*self, *other) }
}
)
}
use std::time::Duration;
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!((), ());
pub fn antichain_join<T: Lattice>(one: &[T], other: &[T]) -> Antichain<T> {
let mut upper = Antichain::new();
antichain_join_into(one, other, &mut upper);
upper
}
pub fn antichain_join_into<T: Lattice>(one: &[T], other: &[T], upper: &mut Antichain<T>) {
upper.clear();
for time1 in one {
for time2 in other {
upper.insert(time1.join(time2));
}
}
}
pub fn antichain_meet<T: Lattice+Clone>(one: &[T], other: &[T]) -> Antichain<T> {
let mut upper = Antichain::new();
for time1 in one {
upper.insert(time1.clone());
}
for time2 in other {
upper.insert(time2.clone());
}
upper
}
impl<T: Lattice+Clone> Lattice for Antichain<T> {
fn join(&self, other: &Self) -> Self {
let mut upper = Antichain::new();
for time1 in self.elements().iter() {
for time2 in other.elements().iter() {
upper.insert(time1.join(time2));
}
}
upper
}
fn meet(&self, other: &Self) -> Self {
let mut upper = Antichain::new();
for time1 in self.elements().iter() {
upper.insert(time1.clone());
}
for time2 in other.elements().iter() {
upper.insert(time2.clone());
}
upper
}
}