more stuff fixed
This commit is contained in:
@@ -19,6 +19,8 @@ along with range_bounds_map. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::ops::{Bound, RangeBounds};
|
||||
|
||||
use crate::range_bounds_map::DiscreteRange;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct DiscreteBounds<I> {
|
||||
//both are always included
|
||||
@@ -34,3 +36,13 @@ impl<I> RangeBounds<I> for DiscreteBounds<I> {
|
||||
Bound::Included(&self.end)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> DiscreteRange<I> for DiscreteBounds<I> {
|
||||
fn start(&self) -> I {
|
||||
self.start
|
||||
}
|
||||
|
||||
fn end(&self) -> I {
|
||||
self.end
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -227,7 +227,5 @@ pub mod range_bounds_map;
|
||||
pub mod range_bounds_set;
|
||||
|
||||
pub use crate::discrete_bounds::DiscreteBounds;
|
||||
pub use crate::range_bounds_map::{
|
||||
OverlapError, OverlapOrTryFromDiscreteBoundsError, RangeBoundsMap,
|
||||
};
|
||||
pub use crate::range_bounds_map::{OverlapError, RangeBoundsMap};
|
||||
pub use crate::range_bounds_set::RangeBoundsSet;
|
||||
|
||||
+152
-222
@@ -21,7 +21,6 @@ use std::cmp::Ordering;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::iter::once;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::RangeBounds;
|
||||
|
||||
use btree_monstrousity::btree_map::{IntoIter as BTreeMapIntoIter, SearchBoundCustom};
|
||||
use btree_monstrousity::BTreeMap;
|
||||
@@ -611,9 +610,9 @@ where
|
||||
.copied();
|
||||
|
||||
if let Some(left) = left_overlapping && let Some(right) = right_overlapping && left.start() == right.start() {
|
||||
Ok(Either::Left(self.cut_single_overlapping(range, left)?))
|
||||
Either::Left(self.cut_single_overlapping(range, left))
|
||||
} else {
|
||||
Ok(Either::Right(self.cut_non_single_overlapping(range, left_overlapping, right_overlapping)?))
|
||||
Either::Right(self.cut_non_single_overlapping(range, left_overlapping, right_overlapping))
|
||||
}
|
||||
}
|
||||
fn cut_single_overlapping<Q>(
|
||||
@@ -630,11 +629,11 @@ where
|
||||
|
||||
let cut_result = cut_range(single_overlapping_range, range);
|
||||
let returning_before_cut = match cut_result.before_cut {
|
||||
Some(before_cut) => Some(K::try_from_discrete_bounds(before_cut)?),
|
||||
Some(before_cut) => Some(K::from(before_cut)),
|
||||
None => None,
|
||||
};
|
||||
let returning_after_cut = match cut_result.after_cut {
|
||||
Some(after_cut) => Some(K::try_from_discrete_bounds(after_cut)?),
|
||||
Some(after_cut) => Some(K::from(after_cut)),
|
||||
None => None,
|
||||
};
|
||||
|
||||
@@ -647,7 +646,7 @@ where
|
||||
self.insert_unchecked(after, value.clone());
|
||||
}
|
||||
|
||||
Ok(once((cut_result.inside_cut.unwrap(), value)))
|
||||
once((cut_result.inside_cut.unwrap(), value))
|
||||
}
|
||||
fn cut_non_single_overlapping<'a, Q>(
|
||||
&'a mut self,
|
||||
@@ -668,7 +667,7 @@ where
|
||||
|
||||
Some((
|
||||
match cut_result.before_cut {
|
||||
Some(before_cut) => Some(K::try_from_discrete_bounds(before_cut)?),
|
||||
Some(before_cut) => Some(K::from(before_cut)),
|
||||
None => None,
|
||||
},
|
||||
cut_result.inside_cut.unwrap(),
|
||||
@@ -682,7 +681,7 @@ where
|
||||
|
||||
Some((
|
||||
match cut_result.after_cut {
|
||||
Some(after_cut) => Some(K::try_from_discrete_bounds(after_cut)?),
|
||||
Some(after_cut) => Some(K::from(after_cut)),
|
||||
None => None,
|
||||
},
|
||||
cut_result.inside_cut.unwrap(),
|
||||
@@ -709,18 +708,18 @@ where
|
||||
let keeping_after_entry = after_config
|
||||
.map(|(_, keeping_after_entry)| (keeping_after_entry, after_value.unwrap()));
|
||||
|
||||
return Ok(keeping_before_entry
|
||||
return keeping_before_entry
|
||||
.into_iter()
|
||||
.chain(self.remove_overlapping(range).map(|(key, value)| {
|
||||
(
|
||||
(DiscreteBounds {
|
||||
start: key.start().into(),
|
||||
end: key.end().into(),
|
||||
start: key.start(),
|
||||
end: key.end(),
|
||||
}),
|
||||
value,
|
||||
)
|
||||
}))
|
||||
.chain(keeping_after_entry.into_iter()));
|
||||
.chain(keeping_after_entry.into_iter());
|
||||
}
|
||||
|
||||
/// Returns an iterator of ranges over all the maximally-sized
|
||||
@@ -813,8 +812,8 @@ where
|
||||
.collect::<Vec<_>>()
|
||||
.windows(2)
|
||||
.map(|windows| DiscreteBounds {
|
||||
start: windows[0].1.up_if_finite().into(),
|
||||
end: windows[1].0.down_if_finite().into(),
|
||||
start: windows[0].1.up().unwrap(),
|
||||
end: windows[1].0.down().unwrap(),
|
||||
})
|
||||
.filter(|range| is_valid_range(*range))
|
||||
//optimisation this would also then be unneccessary
|
||||
@@ -923,20 +922,18 @@ where
|
||||
let matching_end = get_end(self, &value);
|
||||
|
||||
let returning = match (matching_start, matching_end) {
|
||||
(Some(matching_start), Some(matching_end)) => {
|
||||
K::try_from_discrete_bounds(DiscreteBounds {
|
||||
start: matching_start.start().into(),
|
||||
end: matching_end.end().into(),
|
||||
})?
|
||||
}
|
||||
(Some(matching_start), None) => K::try_from_discrete_bounds(DiscreteBounds {
|
||||
start: matching_start.start().into(),
|
||||
end: range.end().into(),
|
||||
})?,
|
||||
(None, Some(matching_end)) => K::try_from_discrete_bounds(DiscreteBounds {
|
||||
start: range.start().into(),
|
||||
end: matching_end.end().into(),
|
||||
})?,
|
||||
(Some(matching_start), Some(matching_end)) => K::from(DiscreteBounds {
|
||||
start: matching_start.start(),
|
||||
end: matching_end.end(),
|
||||
}),
|
||||
(Some(matching_start), None) => K::from(DiscreteBounds {
|
||||
start: matching_start.start(),
|
||||
end: range.end(),
|
||||
}),
|
||||
(None, Some(matching_end)) => K::from(DiscreteBounds {
|
||||
start: range.start(),
|
||||
end: matching_end.end(),
|
||||
}),
|
||||
(None, None) => range,
|
||||
};
|
||||
|
||||
@@ -947,7 +944,7 @@ where
|
||||
|
||||
self.insert_unchecked(returning, value);
|
||||
|
||||
Ok(returning)
|
||||
return returning;
|
||||
}
|
||||
|
||||
/// Adds a new entry to the map and merges into other ranges in
|
||||
@@ -1372,7 +1369,7 @@ where
|
||||
{
|
||||
invalid_range_panic(range);
|
||||
|
||||
let _ = self.cut(range)?;
|
||||
let _ = self.cut(range);
|
||||
self.insert_unchecked(range, value);
|
||||
}
|
||||
|
||||
@@ -1618,7 +1615,7 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
use crate::test_ranges::{ee, ei, ie, ii, iu, ue, ui, uu};
|
||||
use crate::utils::{config, Config, CutResult};
|
||||
use crate::utils::{config, contains_point, Config, CutResult};
|
||||
|
||||
//only every other number to allow mathematical_overlapping_definition
|
||||
//to test between bounds in finite using smaller intervalled finite
|
||||
@@ -1635,49 +1632,41 @@ mod tests {
|
||||
])
|
||||
.unwrap()
|
||||
}
|
||||
fn basic_slice() -> [(DiscreteBounds<i8>, bool); 4] {
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ie(14, 16), true),
|
||||
]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_strict_tests() {
|
||||
assert_insert_strict(
|
||||
basic(),
|
||||
(ii(0, 4), false),
|
||||
Err(OverlapError),
|
||||
None::<[_; 0]>,
|
||||
);
|
||||
assert_insert_strict(
|
||||
basic(),
|
||||
(ii(5, 6), false),
|
||||
Err(OverlapError),
|
||||
None::<[_; 0]>,
|
||||
);
|
||||
assert_insert_strict(basic(), (ii(4, 5), true), Err(OverlapError), None::<[_; 0]>);
|
||||
assert_insert_strict(basic(), (ii(0, 4), false), Err(OverlapError), basic_slice());
|
||||
assert_insert_strict(basic(), (ii(5, 6), false), Err(OverlapError), basic_slice());
|
||||
assert_insert_strict(basic(), (ii(4, 5), true), Err(OverlapError), basic_slice());
|
||||
assert_insert_strict(
|
||||
basic(),
|
||||
(ei(4, 5), true),
|
||||
Ok(()),
|
||||
Some([
|
||||
[
|
||||
(ui(4), false),
|
||||
(ei(4, 5), true),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ie(14, 16), true),
|
||||
]),
|
||||
],
|
||||
);
|
||||
}
|
||||
fn assert_insert_strict<const N: usize>(
|
||||
mut before: RangeBoundsMap<i8, DiscreteBounds<i8>, bool>,
|
||||
to_insert: (DiscreteBounds<i8>, bool),
|
||||
result: Result<(), OverlapError>,
|
||||
after: Option<[(DiscreteBounds<i8>, bool); N]>,
|
||||
after: [(DiscreteBounds<i8>, bool); N],
|
||||
) {
|
||||
let clone = before.clone();
|
||||
assert_eq!(before.insert_strict(to_insert.0, to_insert.1), result);
|
||||
match after {
|
||||
Some(after) => {
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap())
|
||||
}
|
||||
None => assert_eq!(before, clone),
|
||||
}
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1800,58 +1789,50 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn cut_tests() {
|
||||
assert_cut(basic(), ii(50, 60), Ok([]), None::<[_; 0]>);
|
||||
assert_cut(
|
||||
basic(),
|
||||
uu(),
|
||||
Ok([
|
||||
ii(50, 60),
|
||||
[],
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ie(14, 16), true),
|
||||
]),
|
||||
Some([]),
|
||||
],
|
||||
);
|
||||
assert_cut(
|
||||
basic(),
|
||||
uu(),
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ie(14, 16), true),
|
||||
],
|
||||
[],
|
||||
);
|
||||
assert_cut(
|
||||
basic(),
|
||||
ui(6),
|
||||
Ok([(ui(4), false), (ei(5, 6), true)]),
|
||||
Some([(ii(7, 7), false), (ie(14, 16), true)]),
|
||||
[(ui(4), false), (ei(5, 6), true)],
|
||||
[(ii(7, 7), false), (ie(14, 16), true)],
|
||||
);
|
||||
assert_cut(
|
||||
basic(),
|
||||
iu(6),
|
||||
Ok([(ie(6, 7), true), (ii(7, 7), false), (ie(14, 16), true)]),
|
||||
Some([(ui(4), false)]),
|
||||
[(ie(6, 7), true), (ii(7, 7), false), (ie(14, 16), true)],
|
||||
[(ui(4), false)],
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_cut<const N: usize, const Y: usize>(
|
||||
mut before: RangeBoundsMap<I, K, V>,
|
||||
to_cut: Q,
|
||||
result: Result<[(DiscreteBounds<I>, V); Y], TryFromDiscreteBoundsError>,
|
||||
after: Option<[(K, V); N]>,
|
||||
) where
|
||||
I: Ord + Debug + Copy + Discrete,
|
||||
K: DiscreteRange<I> + TryFromDiscreteBounds<I> + PartialEq + Debug + Copy,
|
||||
Q: DiscreteRange<I> + Copy,
|
||||
V: PartialEq + Debug + Clone,
|
||||
{
|
||||
mut before: RangeBoundsMap<i8, DiscreteBounds<i8>, bool>,
|
||||
to_cut: DiscreteBounds<i8>,
|
||||
result: [(DiscreteBounds<i8>, bool); Y],
|
||||
after: [(DiscreteBounds<i8>, bool); N],
|
||||
) {
|
||||
let clone = before.clone();
|
||||
match before.cut(to_cut) {
|
||||
Ok(iter) => {
|
||||
assert_eq!(iter.collect::<Vec<_>>(), result.unwrap());
|
||||
}
|
||||
Err(x) => {
|
||||
assert_eq!(x, result.unwrap_err());
|
||||
}
|
||||
}
|
||||
match after {
|
||||
Some(after) => {
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap())
|
||||
}
|
||||
None => assert_eq!(before, clone),
|
||||
}
|
||||
assert_eq!(before.cut(to_cut).collect::<Vec<_>>(), result);
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1893,124 +1874,109 @@ mod tests {
|
||||
assert_insert_merge_touching(
|
||||
basic(),
|
||||
(ii(0, 4), false),
|
||||
Err(OverlapOrTryFromDiscreteBoundsError::Overlap(OverlapError)),
|
||||
None::<[_; 0]>,
|
||||
Err(OverlapError),
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ie(14, 16), true),
|
||||
],
|
||||
);
|
||||
assert_insert_merge_touching(
|
||||
basic(),
|
||||
(ee(7, 10), false),
|
||||
Ok(ie(7, 10)),
|
||||
Some([
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ie(7, 10), false),
|
||||
(ie(14, 16), true),
|
||||
]),
|
||||
],
|
||||
);
|
||||
assert_insert_merge_touching(
|
||||
basic(),
|
||||
(ee(7, 11), true),
|
||||
Ok(ie(7, 11)),
|
||||
Some([
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ie(7, 11), true),
|
||||
(ie(14, 16), true),
|
||||
]),
|
||||
],
|
||||
);
|
||||
assert_insert_merge_touching(
|
||||
basic(),
|
||||
(ee(7, 14), false),
|
||||
Ok(ie(7, 16)),
|
||||
Some([(ui(4), false), (ee(5, 7), true), (ie(7, 16), false)]),
|
||||
[(ui(4), false), (ee(5, 7), true), (ie(7, 16), false)],
|
||||
);
|
||||
}
|
||||
fn assert_insert_merge_touching<const N: usize, I, K, V>(
|
||||
mut before: RangeBoundsMap<I, K, V>,
|
||||
to_insert: (K, V),
|
||||
result: Result<K, OverlapOrTryFromDiscreteBoundsError>,
|
||||
after: Option<[(K, V); N]>,
|
||||
) where
|
||||
I: Ord + Debug + Copy + Discrete,
|
||||
K: DiscreteRange<I> + TryFromDiscreteBounds<I> + PartialEq + Debug + Copy,
|
||||
V: PartialEq + Debug + Clone,
|
||||
{
|
||||
let clone = before.clone();
|
||||
fn assert_insert_merge_touching<const N: usize>(
|
||||
mut before: RangeBoundsMap<i8, DiscreteBounds<i8>, bool>,
|
||||
to_insert: (DiscreteBounds<i8>, bool),
|
||||
result: Result<DiscreteBounds<i8>, OverlapError>,
|
||||
after: [(DiscreteBounds<i8>, bool); N],
|
||||
) {
|
||||
assert_eq!(
|
||||
before.insert_merge_touching(to_insert.0, to_insert.1),
|
||||
result
|
||||
);
|
||||
match after {
|
||||
Some(after) => {
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap())
|
||||
}
|
||||
None => assert_eq!(before, clone),
|
||||
}
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap())
|
||||
}
|
||||
#[test]
|
||||
fn insert_merge_touching_if_values_equal_tests() {
|
||||
assert_insert_merge_touching_if_values_equal(
|
||||
basic(),
|
||||
(ii(0, 4), false),
|
||||
Err(OverlapOrTryFromDiscreteBoundsError::Overlap(OverlapError)),
|
||||
None::<[_; 0]>,
|
||||
Err(OverlapError),
|
||||
basic_slice(),
|
||||
);
|
||||
assert_insert_merge_touching_if_values_equal(
|
||||
basic(),
|
||||
(ee(7, 10), false),
|
||||
Ok(ie(7, 10)),
|
||||
Some([
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ie(7, 10), false),
|
||||
(ie(14, 16), true),
|
||||
]),
|
||||
],
|
||||
);
|
||||
assert_insert_merge_touching_if_values_equal(
|
||||
basic(),
|
||||
(ee(7, 11), true),
|
||||
Ok(ee(7, 11)),
|
||||
Some([
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ee(7, 11), true),
|
||||
(ie(14, 16), true),
|
||||
]),
|
||||
],
|
||||
);
|
||||
assert_insert_merge_touching_if_values_equal(
|
||||
basic(),
|
||||
(ee(7, 14), false),
|
||||
Ok(ie(7, 14)),
|
||||
Some([
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ie(7, 14), false),
|
||||
(ie(14, 16), true),
|
||||
]),
|
||||
],
|
||||
);
|
||||
}
|
||||
fn assert_insert_merge_touching_if_values_equal<const N: usize, I, K, V>(
|
||||
mut before: RangeBoundsMap<I, K, V>,
|
||||
to_insert: (K, V),
|
||||
result: Result<K, OverlapOrTryFromDiscreteBoundsError>,
|
||||
after: Option<[(K, V); N]>,
|
||||
) where
|
||||
I: Ord + Debug + Copy + Discrete,
|
||||
K: DiscreteRange<I> + TryFromDiscreteBounds<I> + PartialEq + Debug + Copy,
|
||||
V: Eq + Debug + Clone,
|
||||
{
|
||||
let clone = before.clone();
|
||||
fn assert_insert_merge_touching_if_values_equal<const N: usize>(
|
||||
mut before: RangeBoundsMap<i8, DiscreteBounds<i8>, bool>,
|
||||
to_insert: (DiscreteBounds<i8>, bool),
|
||||
result: Result<DiscreteBounds<i8>, OverlapError>,
|
||||
after: [(DiscreteBounds<i8>, bool); N],
|
||||
) {
|
||||
assert_eq!(
|
||||
before.insert_merge_touching_if_values_equal(to_insert.0, to_insert.1),
|
||||
result
|
||||
);
|
||||
match after {
|
||||
Some(after) => {
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap())
|
||||
}
|
||||
None => assert_eq!(before, clone),
|
||||
}
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2018,65 +1984,55 @@ mod tests {
|
||||
assert_insert_merge_overlapping(
|
||||
basic(),
|
||||
(ii(0, 2), true),
|
||||
Ok(ui(4)),
|
||||
Some([
|
||||
ui(4),
|
||||
[
|
||||
(ui(4), true),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ie(14, 16), true),
|
||||
]),
|
||||
],
|
||||
);
|
||||
assert_insert_merge_overlapping(
|
||||
basic(),
|
||||
(ie(14, 16), false),
|
||||
Ok(ie(14, 16)),
|
||||
Some([
|
||||
ie(14, 16),
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ie(14, 16), false),
|
||||
]),
|
||||
],
|
||||
);
|
||||
assert_insert_merge_overlapping(
|
||||
basic(),
|
||||
(ii(6, 11), false),
|
||||
Ok(ei(5, 11)),
|
||||
Some([(ui(4), false), (ei(5, 11), false), (ie(14, 16), true)]),
|
||||
ei(5, 11),
|
||||
[(ui(4), false), (ei(5, 11), false), (ie(14, 16), true)],
|
||||
);
|
||||
assert_insert_merge_overlapping(
|
||||
basic(),
|
||||
(ii(15, 18), true),
|
||||
Ok(ii(14, 18)),
|
||||
Some([
|
||||
ii(14, 18),
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ii(14, 18), true),
|
||||
]),
|
||||
],
|
||||
);
|
||||
assert_insert_merge_overlapping(basic(), (uu(), false), Ok(uu()), Some([(uu(), false)]));
|
||||
assert_insert_merge_overlapping(basic(), (uu(), false), uu(), [(uu(), false)]);
|
||||
}
|
||||
fn assert_insert_merge_overlapping<const N: usize, I, K, V>(
|
||||
mut before: RangeBoundsMap<I, K, V>,
|
||||
to_insert: (K, V),
|
||||
result: Result<K, TryFromDiscreteBoundsError>,
|
||||
after: Option<[(K, V); N]>,
|
||||
) where
|
||||
I: Ord + Debug + Copy + Discrete,
|
||||
K: DiscreteRange<I> + TryFromDiscreteBounds<I> + PartialEq + Debug + Copy,
|
||||
V: PartialEq + Debug + Clone,
|
||||
{
|
||||
let clone = before.clone();
|
||||
fn assert_insert_merge_overlapping<const N: usize>(
|
||||
mut before: RangeBoundsMap<i8, DiscreteBounds<i8>, bool>,
|
||||
to_insert: (DiscreteBounds<i8>, bool),
|
||||
result: DiscreteBounds<i8>,
|
||||
after: [(DiscreteBounds<i8>, bool); N],
|
||||
) {
|
||||
assert_eq!(
|
||||
before.insert_merge_overlapping(to_insert.0, to_insert.1),
|
||||
result
|
||||
);
|
||||
match after {
|
||||
Some(after) => {
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap())
|
||||
}
|
||||
None => assert_eq!(before, clone),
|
||||
}
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2084,85 +2040,70 @@ mod tests {
|
||||
assert_insert_merge_touching_or_overlapping(
|
||||
RangeBoundsMap::from_slice_strict([(ie(1, 4), false)]).unwrap(),
|
||||
(ie(0, 1), true),
|
||||
Ok(ie(0, 4)),
|
||||
Some([(ie(0, 4), true)]),
|
||||
ie(0, 4),
|
||||
[(ie(0, 4), true)],
|
||||
);
|
||||
|
||||
//copied from insert_merge_overlapping_tests
|
||||
assert_insert_merge_touching_or_overlapping(
|
||||
basic(),
|
||||
(ii(0, 2), true),
|
||||
Ok(ui(4)),
|
||||
Some([
|
||||
ui(4),
|
||||
[
|
||||
(ui(4), true),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ie(14, 16), true),
|
||||
]),
|
||||
],
|
||||
);
|
||||
assert_insert_merge_touching_or_overlapping(
|
||||
basic(),
|
||||
(ie(14, 16), false),
|
||||
Ok(ie(14, 16)),
|
||||
Some([
|
||||
ie(14, 16),
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ie(14, 16), false),
|
||||
]),
|
||||
],
|
||||
);
|
||||
assert_insert_merge_touching_or_overlapping(
|
||||
basic(),
|
||||
(ii(6, 11), false),
|
||||
Ok(ei(5, 11)),
|
||||
Some([(ui(4), false), (ei(5, 11), false), (ie(14, 16), true)]),
|
||||
ei(5, 11),
|
||||
[(ui(4), false), (ei(5, 11), false), (ie(14, 16), true)],
|
||||
);
|
||||
assert_insert_merge_touching_or_overlapping(
|
||||
basic(),
|
||||
(ii(15, 18), true),
|
||||
Ok(ii(14, 18)),
|
||||
Some([
|
||||
ii(14, 18),
|
||||
[
|
||||
(ui(4), false),
|
||||
(ee(5, 7), true),
|
||||
(ii(7, 7), false),
|
||||
(ii(14, 18), true),
|
||||
]),
|
||||
);
|
||||
assert_insert_merge_touching_or_overlapping(
|
||||
basic(),
|
||||
(uu(), false),
|
||||
Ok(uu()),
|
||||
Some([(uu(), false)]),
|
||||
],
|
||||
);
|
||||
assert_insert_merge_touching_or_overlapping(basic(), (uu(), false), uu(), [(uu(), false)]);
|
||||
//the only difference from the insert_merge_overlapping
|
||||
assert_insert_merge_touching_or_overlapping(
|
||||
basic(),
|
||||
(ii(7, 14), false),
|
||||
Ok(ee(5, 16)),
|
||||
Some([(ui(4), false), (ee(5, 16), false)]),
|
||||
ee(5, 16),
|
||||
[(ui(4), false), (ee(5, 16), false)],
|
||||
);
|
||||
}
|
||||
fn assert_insert_merge_touching_or_overlapping<const N: usize, I, K, V>(
|
||||
mut before: RangeBoundsMap<I, K, V>,
|
||||
to_insert: (K, V),
|
||||
result: Result<K, TryFromDiscreteBoundsError>,
|
||||
after: Option<[(K, V); N]>,
|
||||
) where
|
||||
I: Ord + Debug + Copy + Discrete,
|
||||
K: DiscreteRange<I> + TryFromDiscreteBounds<I> + PartialEq + Debug + Copy,
|
||||
V: PartialEq + Debug + Clone,
|
||||
{
|
||||
let clone = before.clone();
|
||||
fn assert_insert_merge_touching_or_overlapping<const N: usize>(
|
||||
mut before: RangeBoundsMap<i8, DiscreteBounds<i8>, bool>,
|
||||
to_insert: (DiscreteBounds<i8>, bool),
|
||||
result: DiscreteBounds<i8>,
|
||||
after: [(DiscreteBounds<i8>, bool); N],
|
||||
) {
|
||||
assert_eq!(
|
||||
before.insert_merge_touching_or_overlapping(to_insert.0, to_insert.1),
|
||||
result
|
||||
);
|
||||
match after {
|
||||
Some(after) => {
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap())
|
||||
}
|
||||
None => assert_eq!(before, clone),
|
||||
}
|
||||
assert_eq!(before, RangeBoundsMap::from_slice_strict(after).unwrap())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2184,7 +2125,7 @@ mod tests {
|
||||
|
||||
let mathematical_definition_of_overlap = NUMBERS_DOMAIN
|
||||
.iter()
|
||||
.any(|x| range1.contains(x) && range2.contains(x));
|
||||
.any(|x| contains_point(range1, *x) && contains_point(range2, *x));
|
||||
|
||||
if our_answer != mathematical_definition_of_overlap {
|
||||
dbg!(range1, range2);
|
||||
@@ -2209,8 +2150,8 @@ mod tests {
|
||||
|
||||
// The definition of a cut is: A && NOT B
|
||||
for x in NUMBERS_DOMAIN {
|
||||
let base_contains = base.contains(x);
|
||||
let cut_contains = cut.contains(x);
|
||||
let base_contains = contains_point(base, *x);
|
||||
let cut_contains = contains_point(base, *x);
|
||||
|
||||
if cut_contains {
|
||||
on_left = false;
|
||||
@@ -2248,7 +2189,7 @@ mod tests {
|
||||
}
|
||||
fn con(x: Option<DiscreteBounds<i8>>, point: &i8) -> bool {
|
||||
match x {
|
||||
Some(y) => y.contains(point),
|
||||
Some(y) => contains_point(y, *point),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
@@ -2294,21 +2235,10 @@ mod tests {
|
||||
|
||||
fn all_valid_test_bounds() -> Vec<DiscreteBounds<i8>> {
|
||||
let mut output = Vec::new();
|
||||
for i in NUMBERS
|
||||
.into_iter()
|
||||
.map(|i| DiscreteBoundOrd::Included(*i))
|
||||
.chain(once(DiscreteBoundOrd::StartUnbounded))
|
||||
{
|
||||
for j in NUMBERS
|
||||
.into_iter()
|
||||
.map(|j| DiscreteBoundOrd::Included(*j))
|
||||
.chain(once(DiscreteBoundOrd::StartUnbounded))
|
||||
{
|
||||
for i in NUMBERS {
|
||||
for j in NUMBERS {
|
||||
if i <= j {
|
||||
output.push(DiscreteBounds {
|
||||
start: i.into(),
|
||||
end: j.into(),
|
||||
});
|
||||
output.push(DiscreteBounds { start: *i, end: *j });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-15
@@ -8,10 +8,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use crate::discrete_bounds::DiscreteBounds;
|
||||
use crate::range_bounds_map::{DiscreteRange, IntoIter as RangeBoundsMapIntoIter};
|
||||
use crate::stepable::Discrete;
|
||||
use crate::try_from_discrete_bounds::TryFromDiscreteBounds;
|
||||
use crate::{
|
||||
OverlapError, OverlapOrTryFromDiscreteBoundsError, RangeBoundsMap, TryFromDiscreteBoundsError,
|
||||
};
|
||||
use crate::{OverlapError, RangeBoundsMap};
|
||||
|
||||
/// An ordered set of non-overlapping ranges based on [`RangeBoundsMap`].
|
||||
///
|
||||
@@ -87,12 +84,12 @@ where
|
||||
pub fn cut<'a, Q>(
|
||||
&'a mut self,
|
||||
range: Q,
|
||||
) -> Result<impl Iterator<Item = DiscreteBounds<I>> + '_, TryFromDiscreteBoundsError>
|
||||
) -> impl Iterator<Item = DiscreteBounds<I>> + '_
|
||||
where
|
||||
Q: DiscreteRange<I> + Copy + 'a,
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
{
|
||||
self.inner.cut(range).map(|x| x.map(first))
|
||||
self.inner.cut(range).map(first)
|
||||
}
|
||||
/// See [`RangeBoundsMap::gaps()`] for more details.
|
||||
pub fn gaps<'a, Q>(
|
||||
@@ -119,16 +116,16 @@ where
|
||||
pub fn insert_merge_touching(
|
||||
&mut self,
|
||||
range: K,
|
||||
) -> Result<K, OverlapOrTryFromDiscreteBoundsError>
|
||||
) -> Result<K, OverlapError>
|
||||
where
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
{
|
||||
self.inner.insert_merge_touching(range, ())
|
||||
}
|
||||
/// See [`RangeBoundsMap::insert_merge_overlapping()`] for more details.
|
||||
pub fn insert_merge_overlapping(&mut self, range: K) -> Result<K, TryFromDiscreteBoundsError>
|
||||
pub fn insert_merge_overlapping(&mut self, range: K) -> K
|
||||
where
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
{
|
||||
self.inner.insert_merge_overlapping(range, ())
|
||||
}
|
||||
@@ -136,16 +133,16 @@ where
|
||||
pub fn insert_merge_touching_or_overlapping(
|
||||
&mut self,
|
||||
range: K,
|
||||
) -> Result<K, TryFromDiscreteBoundsError>
|
||||
) -> K
|
||||
where
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
{
|
||||
self.inner.insert_merge_touching_or_overlapping(range, ())
|
||||
}
|
||||
/// See [`RangeBoundsMap::insert_overwrite()`] for more details.
|
||||
pub fn insert_overwrite(&mut self, range: K) -> Result<(), TryFromDiscreteBoundsError>
|
||||
pub fn insert_overwrite(&mut self, range: K)
|
||||
where
|
||||
K: TryFromDiscreteBounds<I>,
|
||||
K: From<DiscreteBounds<I>>,
|
||||
{
|
||||
self.inner.insert_overwrite(range, ())
|
||||
}
|
||||
|
||||
+16
-58
@@ -1,93 +1,51 @@
|
||||
use std::ops::{Bound, RangeBounds};
|
||||
|
||||
use crate::discrete_bounds::{DiscreteBound, DiscreteBounds};
|
||||
use crate::discrete_bounds::DiscreteBounds;
|
||||
use crate::stepable::Discrete;
|
||||
use crate::{TryFromDiscreteBounds, TryFromDiscreteBoundsError};
|
||||
|
||||
pub fn uu() -> DiscreteBounds<i8> {
|
||||
DiscreteBounds {
|
||||
start: DiscreteBound::Unbounded,
|
||||
end: DiscreteBound::Unbounded,
|
||||
start: i8::MIN,
|
||||
end: i8::MAX,
|
||||
}
|
||||
}
|
||||
pub fn ui(x: i8) -> DiscreteBounds<i8> {
|
||||
DiscreteBounds {
|
||||
start: DiscreteBound::Unbounded,
|
||||
end: DiscreteBound::Included(x),
|
||||
start: i8::MIN,
|
||||
end: x,
|
||||
}
|
||||
}
|
||||
pub fn ue(x: i8) -> DiscreteBounds<i8> {
|
||||
DiscreteBounds {
|
||||
start: DiscreteBound::Unbounded,
|
||||
end: DiscreteBound::Included(x.down().unwrap()),
|
||||
start: i8::MIN,
|
||||
end: x.down().unwrap(),
|
||||
}
|
||||
}
|
||||
pub fn iu(x: i8) -> DiscreteBounds<i8> {
|
||||
DiscreteBounds {
|
||||
start: DiscreteBound::Included(x),
|
||||
end: DiscreteBound::Unbounded,
|
||||
start: x,
|
||||
end: i8::MAX,
|
||||
}
|
||||
}
|
||||
//fn eu(x: i8) -> TestBounds {
|
||||
//(Bound::Excluded(x), Bound::Unbounded)
|
||||
//}
|
||||
pub fn ii(x1: i8, x2: i8) -> DiscreteBounds<i8> {
|
||||
DiscreteBounds {
|
||||
start: DiscreteBound::Included(x1),
|
||||
end: DiscreteBound::Included(x2),
|
||||
}
|
||||
DiscreteBounds { start: x1, end: x2 }
|
||||
}
|
||||
pub fn ie(x1: i8, x2: i8) -> DiscreteBounds<i8> {
|
||||
DiscreteBounds {
|
||||
start: DiscreteBound::Included(x1),
|
||||
end: DiscreteBound::Included(x2.down().unwrap()),
|
||||
start: x1.up().unwrap(),
|
||||
end: x2.down().unwrap(),
|
||||
}
|
||||
}
|
||||
pub fn ei(x1: i8, x2: i8) -> DiscreteBounds<i8> {
|
||||
DiscreteBounds {
|
||||
start: DiscreteBound::Included(x1.up().unwrap()),
|
||||
end: DiscreteBound::Included(x2),
|
||||
start: x1.up().unwrap(),
|
||||
end: x2,
|
||||
}
|
||||
}
|
||||
pub fn ee(x1: i8, x2: i8) -> DiscreteBounds<i8> {
|
||||
DiscreteBounds {
|
||||
start: DiscreteBound::Included(x1.up().unwrap()),
|
||||
end: DiscreteBound::Included(x2.down().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct IEStrict {
|
||||
start: i8,
|
||||
end: i8,
|
||||
}
|
||||
|
||||
pub fn ie_strict(start: i8, end: i8) -> IEStrict {
|
||||
IEStrict { start, end }
|
||||
}
|
||||
|
||||
impl RangeBounds<i8> for IEStrict {
|
||||
fn start_bound(&self) -> std::ops::Bound<&i8> {
|
||||
Bound::Included(&self.start)
|
||||
}
|
||||
fn end_bound(&self) -> Bound<&i8> {
|
||||
Bound::Excluded(&self.end)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromDiscreteBounds<i8> for IEStrict {
|
||||
fn try_from_discrete_bounds(
|
||||
discrete_bounds: DiscreteBounds<i8>,
|
||||
) -> Result<Self, TryFromDiscreteBoundsError>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match (discrete_bounds.start, discrete_bounds.end) {
|
||||
(DiscreteBound::Included(start), DiscreteBound::Included(end)) => Ok(IEStrict {
|
||||
start,
|
||||
end: end.checked_add(1).ok_or(TryFromDiscreteBoundsError)?,
|
||||
}),
|
||||
_ => Err(TryFromDiscreteBoundsError),
|
||||
}
|
||||
start: x1.up().unwrap(),
|
||||
end: x2.down().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
+31
-58
@@ -23,12 +23,9 @@ use crate::discrete_bounds::DiscreteBounds;
|
||||
use crate::range_bounds_map::DiscreteRange;
|
||||
use crate::stepable::Discrete;
|
||||
|
||||
pub(crate) fn cmp_point_with_range<I, K>(
|
||||
point: I,
|
||||
range: K,
|
||||
) -> Ordering
|
||||
pub(crate) fn cmp_point_with_range<I, K>(point: I, range: K) -> Ordering
|
||||
where
|
||||
I: Ord,
|
||||
I: Ord,
|
||||
K: DiscreteRange<I>,
|
||||
{
|
||||
if point < range.start() {
|
||||
@@ -57,20 +54,14 @@ where
|
||||
I: Ord,
|
||||
{
|
||||
if a.start() < b.start() {
|
||||
match (
|
||||
contains_discrete_bound_ord(a, b.start()),
|
||||
contains_discrete_bound_ord(a, b.end()),
|
||||
) {
|
||||
match (contains_point(a, b.start()), contains_point(a, b.end())) {
|
||||
(false, false) => Config::LeftFirstNonOverlapping,
|
||||
(true, false) => Config::LeftFirstPartialOverlap,
|
||||
(true, true) => Config::LeftContainsRight,
|
||||
(false, true) => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
match (
|
||||
contains_discrete_bound_ord(b, a.start()),
|
||||
contains_discrete_bound_ord(b, a.end()),
|
||||
) {
|
||||
match (contains_point(b, a.start()), contains_point(b, a.end())) {
|
||||
(false, false) => Config::RightFirstNonOverlapping,
|
||||
(true, false) => Config::RightFirstPartialOverlap,
|
||||
(true, true) => Config::RightContainsLeft,
|
||||
@@ -80,18 +71,9 @@ where
|
||||
}
|
||||
|
||||
enum SortedConfig<I> {
|
||||
NonOverlapping(
|
||||
(DiscreteBoundOrd<I>, DiscreteBoundOrd<I>),
|
||||
(DiscreteBoundOrd<I>, DiscreteBoundOrd<I>),
|
||||
),
|
||||
PartialOverlap(
|
||||
(DiscreteBoundOrd<I>, DiscreteBoundOrd<I>),
|
||||
(DiscreteBoundOrd<I>, DiscreteBoundOrd<I>),
|
||||
),
|
||||
Swallowed(
|
||||
(DiscreteBoundOrd<I>, DiscreteBoundOrd<I>),
|
||||
(DiscreteBoundOrd<I>, DiscreteBoundOrd<I>),
|
||||
),
|
||||
NonOverlapping(DiscreteBounds<I>, DiscreteBounds<I>),
|
||||
PartialOverlap(DiscreteBounds<I>, DiscreteBounds<I>),
|
||||
Swallowed(DiscreteBounds<I>, DiscreteBounds<I>),
|
||||
}
|
||||
fn sorted_config<I, A, B>(a: A, b: B) -> SortedConfig<I>
|
||||
where
|
||||
@@ -112,15 +94,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn contains_discrete_bound_ord<I, A>(
|
||||
range: A,
|
||||
discrete_bound_ord: DiscreteBoundOrd<I>,
|
||||
) -> bool
|
||||
pub(crate) fn contains_point<I, A>(range: A, point: I) -> bool
|
||||
where
|
||||
A: DiscreteRange<I>,
|
||||
I: Ord,
|
||||
{
|
||||
cmp_point_with_range(discrete_bound_ord, range).is_eq()
|
||||
cmp_point_with_range(point, range).is_eq()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -144,61 +123,55 @@ where
|
||||
match config(base, cut) {
|
||||
Config::LeftFirstNonOverlapping => {
|
||||
result.before_cut = Some(DiscreteBounds {
|
||||
start: base.start().into(),
|
||||
end: base.end().into(),
|
||||
start: base.start(),
|
||||
end: base.end(),
|
||||
});
|
||||
}
|
||||
Config::LeftFirstPartialOverlap => {
|
||||
result.before_cut = Some(DiscreteBounds {
|
||||
start: base.start().into(),
|
||||
end: cut.start().down_if_finite().into(),
|
||||
start: base.start(),
|
||||
end: cut.start().down_if_finite(),
|
||||
});
|
||||
result.inside_cut = Some(DiscreteBounds {
|
||||
start: cut.start().into(),
|
||||
end: base.end().into(),
|
||||
start: cut.start(),
|
||||
end: base.end(),
|
||||
});
|
||||
}
|
||||
Config::LeftContainsRight => {
|
||||
result.before_cut = Some(DiscreteBounds {
|
||||
start: base.start().into(),
|
||||
end: cut.start().down_if_finite().into(),
|
||||
start: base.start(),
|
||||
end: cut.start().down_if_finite(),
|
||||
});
|
||||
result.inside_cut = Some(DiscreteBounds {
|
||||
start: cut.start().into(),
|
||||
end: cut.end().into(),
|
||||
start: cut.start(),
|
||||
end: cut.end(),
|
||||
});
|
||||
result.after_cut = Some(DiscreteBounds {
|
||||
start: cut.end().up_if_finite(),
|
||||
end: base.end(),
|
||||
});
|
||||
// exception for Unbounded-ending things
|
||||
match cut.end() {
|
||||
DiscreteBoundOrd::EndUnbounded => {}
|
||||
_ => {
|
||||
result.after_cut = Some(DiscreteBounds {
|
||||
start: cut.end().up_if_finite().into(),
|
||||
end: base.end().into(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Config::RightFirstNonOverlapping => {
|
||||
result.after_cut = Some(DiscreteBounds {
|
||||
start: base.start().into(),
|
||||
end: base.end().into(),
|
||||
start: base.start(),
|
||||
end: base.end(),
|
||||
});
|
||||
}
|
||||
Config::RightFirstPartialOverlap => {
|
||||
result.after_cut = Some(DiscreteBounds {
|
||||
start: cut.end().up_if_finite().into(),
|
||||
end: base.end().into(),
|
||||
start: cut.end().up_if_finite(),
|
||||
end: base.end(),
|
||||
});
|
||||
result.inside_cut = Some(DiscreteBounds {
|
||||
start: base.start().into(),
|
||||
end: cut.end().into(),
|
||||
start: base.start(),
|
||||
end: cut.end(),
|
||||
});
|
||||
}
|
||||
Config::RightContainsLeft => {
|
||||
result.inside_cut = Some(DiscreteBounds {
|
||||
start: base.start().into(),
|
||||
end: base.end().into(),
|
||||
start: base.start(),
|
||||
end: base.end(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user