use core::cmp::Ordering;
use core::fmt::Debug;
use core::hash::Hash;
#[cfg(feature = "dev")]
use arbitrary::Arbitrary;
use order_theory::{
GreatestElement, LeastElement, LowerSemilattice, PredecessorExceptForLeast,
SuccessorExceptForGreatest, UpperSemilattice,
};
use crate::prelude::*;
#[derive(Clone, Debug)]
#[cfg_attr(feature = "dev", derive(Arbitrary))]
pub struct AreaOfInterest<const MCL: usize, const MCC: usize, const MPL: usize, S> {
area: Area<MCL, MCC, MPL, S>,
max_count: u64,
max_size: u64,
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> AreaOfInterest<MCL, MCC, MPL, S> {
pub fn new(area: Area<MCL, MCC, MPL, S>, max_count: u64, max_size: u64) -> Self {
Self {
area,
max_count,
max_size,
}
}
pub fn area(&self) -> &Area<MCL, MCC, MPL, S> {
&self.area
}
pub fn max_count(&self) -> u64 {
self.max_count
}
pub fn max_size(&self) -> u64 {
self.max_size
}
pub fn set_area(&mut self, new_area: Area<MCL, MCC, MPL, S>) {
self.area = new_area;
}
pub fn set_max_count(&mut self, new_max_count: u64) {
self.max_count = new_max_count;
}
pub fn set_max_size(&mut self, new_max_size: u64) {
self.max_size = new_max_size;
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> AreaOfInterest<MCL, MCC, MPL, S>
where
S: Clone + Ord + PredecessorExceptForLeast + SuccessorExceptForGreatest,
{
pub fn is_empty(&self) -> bool {
self.is_least()
}
pub fn intersection(&self, other: &Self) -> Self {
self.greatest_lower_bound(other)
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> PartialEq<Self>
for AreaOfInterest<MCL, MCC, MPL, S>
where
S: Clone + Ord + PredecessorExceptForLeast + SuccessorExceptForGreatest,
{
fn eq(&self, other: &Self) -> bool {
match (self.is_least(), other.is_least()) {
(true, true) => true,
(true, false) | (false, true) => false,
(false, false) => {
self.area() == other.area()
&& self.max_count() == other.max_count()
&& self.max_size() == other.max_size()
}
}
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> Eq
for AreaOfInterest<MCL, MCC, MPL, S>
where
S: Clone + Ord + PredecessorExceptForLeast + SuccessorExceptForGreatest,
{
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> PartialOrd<Self>
for AreaOfInterest<MCL, MCC, MPL, S>
where
S: Clone + Ord + PredecessorExceptForLeast + SuccessorExceptForGreatest,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (self.is_least(), other.is_least()) {
(true, true) => Some(Ordering::Equal),
(true, false) => Some(Ordering::Less),
(false, true) => Some(Ordering::Greater),
(false, false) => match (
self.area().partial_cmp(other.area())?,
self.max_count().cmp(&other.max_count()),
self.max_size().cmp(&other.max_size()),
) {
(Ordering::Equal, Ordering::Equal, Ordering::Equal) => Some(Ordering::Equal),
(area_cmp, count_cmp, size_cmp) => {
if area_cmp.is_le() && count_cmp.is_le() && size_cmp.is_le() {
Some(Ordering::Less)
} else if area_cmp.is_ge() && count_cmp.is_ge() && size_cmp.is_ge() {
Some(Ordering::Greater)
} else {
None
}
}
},
}
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> LeastElement
for AreaOfInterest<MCL, MCC, MPL, S>
where
S: Clone + Ord + PredecessorExceptForLeast + SuccessorExceptForGreatest,
{
fn least() -> Self {
Self::new(Area::least(), 0, 0)
}
fn is_least(&self) -> bool {
self.max_count() == 0 || self.area().is_least()
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> GreatestElement
for AreaOfInterest<MCL, MCC, MPL, S>
where
S: Clone + Ord + PredecessorExceptForLeast + SuccessorExceptForGreatest,
{
fn greatest() -> Self {
Self::new(Area::greatest(), u64::MAX, u64::MAX)
}
fn is_greatest(&self) -> bool {
self.area().is_greatest() && self.max_count() == u64::MAX && self.max_size() == u64::MAX
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> LowerSemilattice
for AreaOfInterest<MCL, MCC, MPL, S>
where
S: Clone + Ord + PredecessorExceptForLeast + SuccessorExceptForGreatest,
{
fn greatest_lower_bound(&self, other: &Self) -> Self {
Self::new(
self.area().greatest_lower_bound(other.area()),
self.max_count().greatest_lower_bound(&other.max_count()),
self.max_size().greatest_lower_bound(&other.max_size()),
)
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> UpperSemilattice
for AreaOfInterest<MCL, MCC, MPL, S>
where
S: Clone + Ord + PredecessorExceptForLeast + SuccessorExceptForGreatest,
{
fn least_upper_bound(&self, other: &Self) -> Self {
if self.is_least() {
other.clone()
} else if other.is_least() {
self.clone()
} else {
Self::new(
self.area().least_upper_bound(other.area()),
self.max_count().least_upper_bound(&other.max_count()),
self.max_size().least_upper_bound(&other.max_size()),
)
}
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> Hash
for AreaOfInterest<MCL, MCC, MPL, S>
where
S: Hash + Clone + Ord + PredecessorExceptForLeast + SuccessorExceptForGreatest,
{
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
if self.is_least() {
255u8.hash(state);
} else if self.is_greatest() {
254u8.hash(state);
} else {
253u8.hash(state);
self.area.hash(state);
self.max_count.hash(state);
self.max_size.hash(state);
}
}
}