#[cfg(feature = "decimal")]
use decimal::d128;
use std::cmp::{Ordering, PartialOrd};
pub trait MeetSemilattice: Sized {
fn meet(&self, other: &Self) -> Self;
}
pub trait JoinSemilattice: Sized {
fn join(&self, other: &Self) -> Self;
}
pub trait Lattice: MeetSemilattice + JoinSemilattice + PartialOrd {
#[inline]
fn meet_join(&self, other: &Self) -> (Self, Self) {
(self.meet(other), self.join(other))
}
#[inline]
fn partial_min<'a>(&'a self, other: &'a Self) -> Option<&'a Self> {
if let Some(ord) = self.partial_cmp(other) {
match ord {
Ordering::Greater => Some(other),
_ => Some(self),
}
} else {
None
}
}
#[inline]
fn partial_max<'a>(&'a self, other: &'a Self) -> Option<&'a Self> {
if let Some(ord) = self.partial_cmp(other) {
match ord {
Ordering::Less => Some(other),
_ => Some(self),
}
} else {
None
}
}
#[inline]
fn partial_sort2<'a>(&'a self, other: &'a Self) -> Option<(&'a Self, &'a Self)> {
if let Some(ord) = self.partial_cmp(other) {
match ord {
Ordering::Less => Some((self, other)),
_ => Some((other, self)),
}
} else {
None
}
}
#[inline]
fn partial_clamp<'a>(&'a self, min: &'a Self, max: &'a Self) -> Option<&'a Self> {
if let (Some(cmp_min), Some(cmp_max)) = (self.partial_cmp(min), self.partial_cmp(max)) {
if cmp_min == Ordering::Less {
Some(min)
} else if cmp_max == Ordering::Greater {
Some(max)
} else {
Some(self)
}
} else {
None
}
}
}
macro_rules! impl_lattice(
($($T:ident),*) => {$(
impl MeetSemilattice for $T {
#[inline]
fn meet(&self, other: &Self) -> Self {
if *self <= *other {
*self
}
else {
*other
}
}
}
impl JoinSemilattice for $T {
#[inline]
fn join(&self, other: &Self) -> Self {
if *self >= *other {
*self
}
else {
*other
}
}
}
impl Lattice for $T {
#[inline]
fn meet_join(&self, other: &Self) -> (Self, Self) {
if *self >= *other {
(*other, *self)
}
else {
(*self, *other)
}
}
}
)*}
);
impl_lattice!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64);
#[cfg(feature = "decimal")]
impl_lattice!(d128);
impl<N: MeetSemilattice> MeetSemilattice for num_complex::Complex<N> {
#[inline]
fn meet(&self, other: &Self) -> Self {
Self {
re: self.re.meet(&other.re),
im: self.im.meet(&other.im),
}
}
}
impl<N: JoinSemilattice> JoinSemilattice for num_complex::Complex<N> {
#[inline]
fn join(&self, other: &Self) -> Self {
Self {
re: self.re.join(&other.re),
im: self.im.join(&other.im),
}
}
}