Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(utils): Inplace operations and std traits #41

Merged
merged 4 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 142 additions & 63 deletions utils/src/range/difference.rs
Original file line number Diff line number Diff line change
@@ -1,72 +1,30 @@
use std::ops::Range;
use std::ops::{Range, Sub, SubAssign};

use crate::range::{Difference, Disjoint, RangeSet, Subset, Union};
use crate::range::{Disjoint, RangeSet, Subset};

impl<T: Copy + Ord> Difference<Range<T>> for Range<T> {
type Output = RangeSet<T>;

fn difference(&self, other: &Range<T>) -> Self::Output {
if self.is_empty() {
return RangeSet::default();
} else if other.is_empty() {
return RangeSet::from(self.clone());
}

// If other contains self, return an empty set.
if self.is_subset(other) {
return RangeSet::default();
}

// If they are disjoint, return self.
if self.is_disjoint(other) {
return RangeSet::from(self.clone());
}
pub trait Difference<Rhs> {
type Output;

let mut set = RangeSet::default();

if self.start < other.start {
set.ranges.push(self.start..other.start);
}

if self.end > other.end {
set.ranges.push(other.end..self.end);
}

set
}
/// Returns the set difference of `self` and `other`.
#[must_use]
fn difference(&self, other: &Rhs) -> Self::Output;
}

impl<T: Copy + Ord> Difference<RangeSet<T>> for Range<T>
where
RangeSet<T>: Difference<Range<T>, Output = RangeSet<T>>,
{
type Output = RangeSet<T>;

fn difference(&self, other: &RangeSet<T>) -> Self::Output {
if self.is_empty() {
return RangeSet::default();
}

let mut diff = RangeSet::from(self.clone());

for range in &other.ranges {
diff = diff.difference(range);
}

diff
}
pub trait DifferenceMut<Rhs> {
/// Subtracts `other` from `self`.
fn difference_mut(&mut self, other: &Rhs);
}

impl<T: Copy + Ord> Difference<Range<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn difference(&self, other: &Range<T>) -> Self::Output {
impl<T: Copy + Ord> DifferenceMut<Range<T>> for RangeSet<T> {
fn difference_mut(&mut self, other: &Range<T>) {
if other.is_empty() {
return self.clone();
return;
} else if self.ranges.is_empty() {
return;
}

let mut i = 0;
let mut ranges = self.ranges.clone();
let ranges = &mut self.ranges;
while i < ranges.len() {
// If the current range is entirely before other
if ranges[i].end <= other.start {
Expand Down Expand Up @@ -106,27 +64,148 @@ impl<T: Copy + Ord> Difference<Range<T>> for RangeSet<T> {

i += 1;
}
}
}

RangeSet { ranges }
impl<T: Copy + Ord> DifferenceMut<RangeSet<T>> for RangeSet<T> {
fn difference_mut(&mut self, other: &RangeSet<T>) {
for range in &other.ranges {
self.difference_mut(range);
}
}
}

impl<T: Copy + Ord> Difference<RangeSet<T>> for RangeSet<T> {
impl<T: Copy + Ord> Difference<Range<T>> for Range<T> {
type Output = RangeSet<T>;

fn difference(&self, other: &RangeSet<T>) -> Self::Output {
fn difference(&self, other: &Range<T>) -> Self::Output {
if self.is_empty() {
return RangeSet::default();
} else if other.is_empty() {
return RangeSet::from(self.clone());
}

// If other contains self, return an empty set.
if self.is_subset(other) {
return RangeSet::default();
}

// If they are disjoint, return self.
if self.is_disjoint(other) {
return RangeSet::from(self.clone());
}

let mut set = RangeSet::default();
for range in &self.ranges {
set = set.union(&range.difference(other));

if self.start < other.start {
set.ranges.push(self.start..other.start);
}

if self.end > other.end {
set.ranges.push(other.end..self.end);
}

set
}
}

impl<T: Copy + Ord> Difference<Range<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn difference(&self, other: &Range<T>) -> Self::Output {
let mut diff = self.clone();
diff.difference_mut(other);
diff
}
}

impl<T: Copy + Ord> Difference<RangeSet<T>> for Range<T> {
type Output = RangeSet<T>;

fn difference(&self, other: &RangeSet<T>) -> Self::Output {
let mut diff = RangeSet {
ranges: vec![self.clone()],
};
diff.difference_mut(other);
diff
}
}

impl<T: Copy + Ord> Difference<RangeSet<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn difference(&self, other: &RangeSet<T>) -> Self::Output {
let mut diff = self.clone();
diff.difference_mut(other);
diff
}
}

impl<T: Copy + Ord> SubAssign<Range<T>> for RangeSet<T> {
fn sub_assign(&mut self, rhs: Range<T>) {
self.difference_mut(&rhs);
}
}

impl<T: Copy + Ord> SubAssign<&Range<T>> for RangeSet<T> {
fn sub_assign(&mut self, rhs: &Range<T>) {
self.difference_mut(rhs);
}
}

impl<T: Copy + Ord> Sub<Range<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn sub(mut self, rhs: Range<T>) -> Self::Output {
self.difference_mut(&rhs);
self
}
}

impl<T: Copy + Ord> Sub<&Range<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn sub(mut self, rhs: &Range<T>) -> Self::Output {
th4s marked this conversation as resolved.
Show resolved Hide resolved
self.difference_mut(rhs);
self
}
}

impl<T: Copy + Ord> SubAssign<RangeSet<T>> for RangeSet<T> {
fn sub_assign(&mut self, rhs: RangeSet<T>) {
self.difference_mut(&rhs);
}
}

impl<T: Copy + Ord> SubAssign<&RangeSet<T>> for RangeSet<T> {
fn sub_assign(&mut self, rhs: &RangeSet<T>) {
self.difference_mut(rhs);
}
}

impl<T: Copy + Ord> Sub<RangeSet<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn sub(mut self, rhs: RangeSet<T>) -> Self::Output {
self.difference_mut(&rhs);
self
}
}

impl<T: Copy + Ord> Sub<&RangeSet<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn sub(mut self, rhs: &RangeSet<T>) -> Self::Output {
self.difference_mut(rhs);
self
}
}

#[cfg(test)]
#[allow(clippy::all)]
mod tests {
use super::*;
use crate::range::Union;

use itertools::iproduct;

Expand Down
84 changes: 83 additions & 1 deletion utils/src/range/intersection.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
use crate::range::{Intersection, Range, RangeSet};
use std::ops::{BitAnd, BitAndAssign};

use crate::range::{Range, RangeSet};

pub trait Intersection<Rhs> {
type Output;

/// Returns the set intersection of `self` and `other`.
#[must_use]
fn intersection(&self, other: &Rhs) -> Self::Output;
}

impl<T: Copy + Ord> Intersection<Range<T>> for Range<T> {
type Output = Option<Range<T>>;
Expand Down Expand Up @@ -82,6 +92,78 @@ impl<T: Copy + Ord> Intersection<RangeSet<T>> for RangeSet<T> {
}
}

impl<T: Copy + Ord> BitAndAssign<Range<T>> for RangeSet<T> {
fn bitand_assign(&mut self, other: Range<T>) {
*self = self.intersection(&other);
}
}

impl<T: Copy + Ord> BitAndAssign<&Range<T>> for RangeSet<T> {
fn bitand_assign(&mut self, other: &Range<T>) {
*self = self.intersection(other);
}
}

impl<T: Copy + Ord> BitAnd<RangeSet<T>> for Range<T> {
type Output = RangeSet<T>;

fn bitand(self, other: RangeSet<T>) -> Self::Output {
self.intersection(&other)
}
}

impl<T: Copy + Ord> BitAnd<&RangeSet<T>> for Range<T> {
type Output = RangeSet<T>;

fn bitand(self, other: &RangeSet<T>) -> Self::Output {
self.intersection(other)
}
}

impl<T: Copy + Ord> BitAnd<Range<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn bitand(self, other: Range<T>) -> Self::Output {
other.intersection(&self)
}
}

impl<T: Copy + Ord> BitAnd<&Range<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn bitand(self, other: &Range<T>) -> Self::Output {
other.intersection(&self)
}
}

impl<T: Copy + Ord> BitAndAssign<RangeSet<T>> for RangeSet<T> {
fn bitand_assign(&mut self, other: RangeSet<T>) {
*self = self.intersection(&other);
}
}

impl<T: Copy + Ord> BitAndAssign<&RangeSet<T>> for RangeSet<T> {
fn bitand_assign(&mut self, other: &RangeSet<T>) {
*self = self.intersection(other);
}
}

impl<T: Copy + Ord> BitAnd<RangeSet<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn bitand(self, other: RangeSet<T>) -> Self::Output {
self.intersection(&other)
}
}

impl<T: Copy + Ord> BitAnd<&RangeSet<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn bitand(self, other: &RangeSet<T>) -> Self::Output {
self.intersection(other)
}
}

#[cfg(test)]
mod tests {
use std::collections::HashSet;
Expand Down
Loading
Loading