#![allow(unexpected_cfgs)]
use core::cmp::max;
use core::mem;
use core::{
cmp::Ordering,
fmt,
iter::FusedIterator,
ops::{BitOr, BitOrAssign, Bound, RangeBounds, RangeInclusive},
};
use num_traits::{One, Zero};
#[cfg(all(not(coverage), feature = "std"))]
use std::{
fs::File,
io::{self, BufRead, BufReader},
path::Path,
str::FromStr,
};
use crate::alloc::string::ToString;
use crate::sorted_disjoint::RangeOnce;
use alloc::collections::{BTreeMap, btree_map};
use alloc::string::String;
use alloc::vec::Vec;
use gen_ops::gen_ops_ex;
use crate::ranges_iter::RangesIter;
use crate::unsorted_disjoint::{SortedDisjointWithLenSoFar, UnsortedDisjoint};
use crate::{Integer, prelude::*};
use crate::{IntoRangesIter, UnionIter};
#[cfg(all(not(coverage), feature = "std"))]
#[allow(dead_code)]
#[doc(hidden)]
pub fn demo_read_ranges_from_file<P, T>(path: P) -> io::Result<RangeSetBlaze<T>>
where
P: AsRef<Path>,
T: FromStr + Integer,
{
let lines = BufReader::new(File::open(&path)?).lines();
let mut set = RangeSetBlaze::new();
for line in lines {
let line = line?;
let mut split = line.split('\t');
let start = split
.next()
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Missing start of range"))?
.parse::<T>()
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid start of range"))?;
let end = split
.next()
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Missing end of range"))?
.parse::<T>()
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid end of range"))?;
set.ranges_insert(start..=end);
}
Ok(set)
}
#[derive(Clone, Hash, PartialEq)]
pub struct RangeSetBlaze<T: Integer> {
len: <T as Integer>::SafeLen,
pub(crate) btree_map: BTreeMap<T, T>,
}
impl<T: Integer> Default for RangeSetBlaze<T> {
fn default() -> Self {
Self {
len: <T as Integer>::SafeLen::zero(),
btree_map: BTreeMap::new(),
}
}
}
impl<T: Integer> fmt::Debug for RangeSetBlaze<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.ranges().into_string())
}
}
impl<T: Integer> fmt::Display for RangeSetBlaze<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.ranges().into_string())
}
}
impl<T: Integer> RangeSetBlaze<T> {
#[allow(clippy::iter_without_into_iter)]
pub fn iter(&self) -> Iter<T, RangesIter<'_, T>> {
Iter {
range_front: T::exhausted_range(),
range_back: T::exhausted_range(),
btree_set_iter: self.ranges(),
}
}
#[must_use]
pub fn first(&self) -> Option<T> {
self.btree_map.iter().next().map(|(x, _)| *x)
}
pub fn get(&self, value: T) -> Option<T> {
if self.contains(value) {
Some(value)
} else {
None
}
}
#[must_use]
pub fn last(&self) -> Option<T> {
self.btree_map.iter().next_back().map(|(_, x)| *x)
}
pub fn from_sorted_disjoint<I>(iter: I) -> Self
where
I: SortedDisjoint<T>,
{
let mut iter_with_len = SortedDisjointWithLenSoFar::new(iter);
let btree_map = (&mut iter_with_len).collect();
Self {
btree_map,
len: iter_with_len.len_so_far(),
}
}
#[cfg(feature = "from_slice")]
#[inline]
pub fn from_slice(slice: impl AsRef<[T]>) -> Self {
T::from_slice(slice)
}
#[allow(dead_code)]
#[must_use]
pub(crate) fn len_slow(&self) -> <T as Integer>::SafeLen {
Self::btree_map_len(&self.btree_map)
}
pub fn append(&mut self, other: &mut Self) {
for range in other.ranges() {
self.internal_add(range);
}
other.clear();
}
pub fn clear(&mut self) {
self.btree_map.clear();
self.len = <T as Integer>::SafeLen::zero();
}
#[must_use]
#[inline]
pub fn is_empty(&self) -> bool {
self.ranges_len() == 0
}
#[must_use]
#[inline]
pub fn is_universal(&self) -> bool {
self.ranges().is_universal()
}
#[must_use]
#[inline]
pub fn is_subset(&self, other: &Self) -> bool {
if self.len() > other.len() {
return false;
}
self.ranges().is_subset(other.ranges())
}
#[must_use]
pub fn is_superset(&self, other: &Self) -> bool {
other.is_subset(self)
}
pub fn contains(&self, value: T) -> bool {
self.btree_map
.range(..=value)
.next_back()
.is_some_and(|(_, end)| value <= *end)
}
#[must_use]
#[inline]
pub fn is_disjoint(&self, other: &Self) -> bool {
self.ranges().is_disjoint(other.ranges())
}
fn delete_extra(&mut self, internal_range: &RangeInclusive<T>) {
let (start, end) = internal_range.clone().into_inner();
let mut after = self.btree_map.range_mut(start..);
let (start_after, end_after) = after
.next()
.expect("Real assert: there will always be a next");
debug_assert!(start == *start_after && end == *end_after);
let mut end_new = end;
let delete_list = after
.map_while(|(start_delete, end_delete)| {
if *start_delete <= end || *start_delete <= end.add_one() {
end_new = max(end_new, *end_delete);
self.len -= T::safe_len(&(*start_delete..=*end_delete));
Some(*start_delete)
} else {
None
}
})
.collect::<Vec<_>>();
if end_new > end {
self.len += T::safe_len(&(end..=end_new.sub_one()));
*end_after = end_new;
}
for start in delete_list {
self.btree_map.remove(&start);
}
}
pub fn insert(&mut self, value: T) -> bool {
let len_before = self.len;
self.internal_add(value..=value);
self.len != len_before
}
pub fn range<R>(&self, range: R) -> IntoIter<T>
where
R: RangeBounds<T>,
{
let (start, end) = extract_range(range);
assert!(
start <= end,
"start (inclusive) must be less than or equal to end (inclusive)"
);
let bounds = CheckSortedDisjoint::new([start..=end]);
Self::from_sorted_disjoint(self.ranges() & bounds).into_iter()
}
pub fn ranges_insert<R>(&mut self, range: R) -> bool
where
R: RangeBounds<T>,
{
let len_before = self.len;
let (start, end) = extract_range(range);
self.internal_add(start..=end);
self.len != len_before
}
pub fn remove(&mut self, value: T) -> bool {
let Some((start_ref, end_ref)) = self.btree_map.range_mut(..=value).next_back() else {
return false;
};
let end = *end_ref;
if end < value {
return false;
}
let start = *start_ref;
if start < value {
*end_ref = value.sub_one();
if value == end {
self.len -= <T::SafeLen>::one();
return true;
}
}
self.len -= <T::SafeLen>::one();
if start == value {
self.btree_map.remove(&start);
}
if value < end {
self.btree_map.insert(value.add_one(), end);
}
true
}
#[must_use]
pub fn split_off(&mut self, key: T) -> Self {
let old_len = self.len;
let old_btree_len = self.btree_map.len();
let mut new_btree = self.btree_map.split_off(&key);
let Some(last_entry) = self.btree_map.last_entry() else {
self.len = T::SafeLen::zero();
return Self {
btree_map: new_btree,
len: old_len,
};
};
let end = *last_entry.get();
if end < key {
let (a_len, b_len) = self.two_element_lengths(old_btree_len, &new_btree, old_len);
self.len = a_len;
return Self {
btree_map: new_btree,
len: b_len,
};
}
*(last_entry.into_mut()) = key.sub_one();
new_btree.insert(key, end);
let (a_len, b_len) = self.two_element_lengths(old_btree_len, &new_btree, old_len);
self.len = a_len;
Self {
btree_map: new_btree,
len: b_len,
}
}
fn two_element_lengths(
&self,
old_btree_len: usize,
new_btree: &BTreeMap<T, T>,
mut old_len: <T as Integer>::SafeLen,
) -> (<T as Integer>::SafeLen, <T as Integer>::SafeLen) {
if old_btree_len / 2 < new_btree.len() {
let a_len = Self::btree_map_len(&self.btree_map);
old_len -= a_len;
(a_len, old_len)
} else {
let b_len = Self::btree_map_len(new_btree);
old_len -= b_len;
(old_len, b_len)
}
}
fn btree_map_len(btree_map: &BTreeMap<T, T>) -> T::SafeLen {
btree_map
.iter()
.fold(<T as Integer>::SafeLen::zero(), |acc, (start, end)| {
acc + T::safe_len(&(*start..=*end))
})
}
pub fn take(&mut self, value: T) -> Option<T> {
if self.remove(value) {
Some(value)
} else {
None
}
}
pub fn replace(&mut self, value: T) -> Option<T> {
if self.insert(value) {
None
} else {
Some(value)
}
}
pub(crate) fn internal_add(&mut self, range: RangeInclusive<T>) {
let (start, end) = range.clone().into_inner();
if end < start {
return;
}
let mut before = self.btree_map.range_mut(..=start).rev();
if let Some((start_before, end_before)) = before.next() {
if (*end_before)
.checked_add_one()
.is_some_and(|end_before_succ| end_before_succ < start)
{
self.internal_add2(&range);
} else if *end_before < end {
self.len += T::safe_len(&(*end_before..=end.sub_one()));
*end_before = end;
let start_before = *start_before;
self.delete_extra(&(start_before..=end));
} else {
}
} else {
self.internal_add2(&range);
}
}
#[inline]
fn internal_add2(&mut self, internal_range: &RangeInclusive<T>) {
let (start, end) = internal_range.clone().into_inner();
let was_there = self.btree_map.insert(start, end);
debug_assert!(was_there.is_none()); self.delete_extra(internal_range);
self.len += T::safe_len(internal_range);
}
#[must_use]
pub const fn len(&self) -> <T as Integer>::SafeLen {
self.len
}
#[must_use]
#[inline]
pub fn new() -> Self {
Self {
btree_map: BTreeMap::new(),
len: <T as Integer>::SafeLen::zero(),
}
}
pub fn pop_first(&mut self) -> Option<T> {
if let Some(entry) = self.btree_map.first_entry() {
let (start, end) = entry.remove_entry();
self.len -= T::safe_len(&(start..=end));
if start != end {
let start = start.add_one();
self.btree_map.insert(start, end);
self.len += T::safe_len(&(start..=end));
}
Some(start)
} else {
None
}
}
pub fn pop_last(&mut self) -> Option<T> {
let mut entry = self.btree_map.last_entry()?;
let start = *entry.key();
let end = entry.get_mut();
let result = *end;
self.len -= T::safe_len(&(start..=*end));
if start == *end {
entry.remove_entry();
} else {
(*end).assign_sub_one();
self.len += T::safe_len(&(start..=*end));
}
Some(result)
}
pub fn ranges(&self) -> RangesIter<'_, T> {
RangesIter {
iter: self.btree_map.iter(),
}
}
pub fn into_ranges(self) -> IntoRangesIter<T> {
IntoRangesIter {
iter: self.btree_map.into_iter(),
}
}
#[deprecated(since = "0.2.0", note = "Use `RangeSetBlaze::to_string` instead.")]
pub fn into_string(&self) -> String {
self.to_string()
}
#[must_use]
pub fn ranges_len(&self) -> usize {
self.btree_map.len()
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
*self = self.iter().filter(|t| f(t)).collect();
}
pub fn ranges_retain<F>(&mut self, mut f: F)
where
F: FnMut(&RangeInclusive<T>) -> bool,
{
self.btree_map.retain(|start, end| {
let range = *start..=*end;
if f(&range) {
true
} else {
self.len -= T::safe_len(&range);
false
}
});
}
}
impl<T: Integer> FromIterator<T> for RangeSetBlaze<T> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = T>,
{
iter.into_iter().map(|x| x..=x).collect()
}
}
impl<'a, T: Integer> FromIterator<&'a T> for RangeSetBlaze<T> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = &'a T>,
{
iter.into_iter().map(|x| *x..=*x).collect()
}
}
impl<T: Integer> FromIterator<RangeInclusive<T>> for RangeSetBlaze<T> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = RangeInclusive<T>>,
{
let union_iter: UnionIter<T, _> = iter.into_iter().collect();
Self::from_sorted_disjoint(union_iter)
}
}
impl<'a, T: Integer> FromIterator<&'a RangeInclusive<T>> for RangeSetBlaze<T> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = &'a RangeInclusive<T>>,
{
let union_iter: UnionIter<T, _> = iter.into_iter().cloned().collect();
Self::from_sorted_disjoint(union_iter)
}
}
impl<T: Integer, const N: usize> From<[T; N]> for RangeSetBlaze<T> {
#[cfg(not(feature = "from_slice"))]
fn from(arr: [T; N]) -> Self {
arr.into_iter().collect()
}
#[cfg(feature = "from_slice")]
fn from(arr: [T; N]) -> Self {
Self::from_slice(arr)
}
}
impl<T: Integer> From<RangeInclusive<T>> for RangeSetBlaze<T> {
fn from(value: RangeInclusive<T>) -> Self {
Self::from_sorted_disjoint(RangeOnce::new(value))
}
}
gen_ops_ex!(
<T>;
types ref RangeSetBlaze<T>, ref RangeSetBlaze<T> => RangeSetBlaze<T>;
for & call |a: &RangeSetBlaze<T>, b: &RangeSetBlaze<T>| {
(a.ranges() & b.ranges()).into_range_set_blaze()
};
for ^ call |a: &RangeSetBlaze<T>, b: &RangeSetBlaze<T>| {
a.ranges().symmetric_difference(b.ranges()).into_range_set_blaze()
};
for - call |a: &RangeSetBlaze<T>, b: &RangeSetBlaze<T>| {
(a.ranges() - b.ranges()).into_range_set_blaze()
};
where T: Integer );
gen_ops_ex!(
<T>;
types ref RangeSetBlaze<T> => RangeSetBlaze<T>;
for ! call |a: &RangeSetBlaze<T>| {
(!a.ranges()).into_range_set_blaze()
};
where T: Integer );
impl<'a, T: Integer> IntoIterator for &'a RangeSetBlaze<T> {
type Item = T;
type IntoIter = Iter<T, RangesIter<'a, T>>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<T: Integer> IntoIterator for RangeSetBlaze<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
IntoIter {
option_range_front: None,
option_range_back: None,
btree_map_into_iter: self.btree_map.into_iter(),
}
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)]
#[allow(clippy::struct_field_names)]
pub struct Iter<T, I> {
btree_set_iter: I,
range_front: RangeInclusive<T>,
range_back: RangeInclusive<T>,
}
impl<T: Integer, I> FusedIterator for Iter<T, I> where I: SortedDisjoint<T> + FusedIterator {}
impl<T: Integer, I> Iterator for Iter<T, I>
where
I: SortedDisjoint<T>,
{
type Item = T;
fn next(&mut self) -> Option<T> {
if let Some(next_item) = T::range_next(&mut self.range_front) {
return Some(next_item);
}
if let Some(next_range) = self.btree_set_iter.next() {
debug_assert!(next_range.start() <= next_range.end()); self.range_front = next_range;
return T::range_next(&mut self.range_front); }
self.range_front = mem::replace(&mut self.range_back, T::exhausted_range());
T::range_next(&mut self.range_front)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, _high) = self.btree_set_iter.size_hint();
(low, None)
}
}
impl<T: Integer, I> DoubleEndedIterator for Iter<T, I>
where
I: SortedDisjoint<T> + DoubleEndedIterator,
{
fn next_back(&mut self) -> Option<Self::Item> {
if let Some(next_item) = T::range_next_back(&mut self.range_back) {
return Some(next_item);
}
if let Some(next_back_range) = self.btree_set_iter.next_back() {
debug_assert!(next_back_range.start() <= next_back_range.end()); self.range_back = next_back_range;
return T::range_next_back(&mut self.range_back); }
self.range_back = mem::replace(&mut self.range_front, T::exhausted_range());
T::range_next_back(&mut self.range_back)
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Debug)]
#[allow(clippy::struct_field_names)]
pub struct IntoIter<T> {
option_range_front: Option<RangeInclusive<T>>,
option_range_back: Option<RangeInclusive<T>>,
btree_map_into_iter: btree_map::IntoIter<T, T>,
}
impl<T: Integer> FusedIterator for IntoIter<T> {}
impl<T: Integer> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let range = self
.option_range_front
.take()
.or_else(|| {
self.btree_map_into_iter
.next()
.map(|(start, end)| start..=end)
})
.or_else(|| self.option_range_back.take())?;
let (start, end) = range.into_inner();
debug_assert!(start <= end);
if start < end {
self.option_range_front = Some(start.add_one()..=end);
}
Some(start)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, _high) = self.btree_map_into_iter.size_hint();
(low, None)
}
}
impl<T: Integer> DoubleEndedIterator for IntoIter<T> {
fn next_back(&mut self) -> Option<Self::Item> {
let range = self
.option_range_back
.take()
.or_else(|| {
self.btree_map_into_iter
.next_back()
.map(|(start, end)| start..=end)
})
.or_else(|| self.option_range_front.take())?;
let (start, end) = range.into_inner();
debug_assert!(start <= end);
if start < end {
self.option_range_back = Some(start..=end.sub_one());
}
Some(end)
}
}
impl<T: Integer> Extend<T> for RangeSetBlaze<T> {
#[inline]
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = T>,
{
let iter = iter.into_iter();
for range in UnsortedDisjoint::new(iter.map(|x| x..=x)) {
self.internal_add(range);
}
}
}
impl<T: Integer> BitOrAssign<&Self> for RangeSetBlaze<T> {
fn bitor_assign(&mut self, other: &Self) {
let b_len = other.ranges_len();
if b_len == 0 {
return;
}
let a_len = self.ranges_len();
if a_len == 0 {
*self = other.clone();
return;
}
let a_len_log2: usize = a_len
.ilog2()
.try_into() .expect(
"ilog2 result always fits in usize on our targets so this will be optimized away",
);
if b_len * (a_len_log2 + 1) < a_len + b_len {
for (start, end) in &other.btree_map {
self.internal_add(*start..=*end);
}
} else {
*self = (self.ranges() | other.ranges()).into_range_set_blaze();
}
}
}
impl<T: Integer> BitOrAssign<Self> for RangeSetBlaze<T> {
fn bitor_assign(&mut self, mut other: Self) {
let a_len = self.ranges_len();
let b_len = other.ranges_len();
if b_len <= a_len {
*self |= &other;
} else {
other |= &*self;
*self = other;
}
}
}
impl<T: Integer> BitOr<Self> for RangeSetBlaze<T> {
type Output = Self;
fn bitor(mut self, other: Self) -> Self {
self |= other;
self
}
}
impl<T: Integer> BitOr<&Self> for RangeSetBlaze<T> {
type Output = Self;
fn bitor(mut self, other: &Self) -> Self {
self |= other;
self
}
}
impl<T: Integer> BitOr<RangeSetBlaze<T>> for &RangeSetBlaze<T> {
type Output = RangeSetBlaze<T>;
fn bitor(self, mut other: RangeSetBlaze<T>) -> RangeSetBlaze<T> {
other |= self;
other
}
}
impl<T: Integer> BitOr<&RangeSetBlaze<T>> for &RangeSetBlaze<T> {
type Output = RangeSetBlaze<T>;
fn bitor(self, other: &RangeSetBlaze<T>) -> RangeSetBlaze<T> {
if other.ranges_len() == 0 {
return self.clone();
}
if self.ranges_len() == 0 {
return other.clone();
}
(self.ranges() | other.ranges()).into_range_set_blaze()
}
}
impl<T: Integer> Extend<RangeInclusive<T>> for RangeSetBlaze<T> {
#[inline]
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = RangeInclusive<T>>,
{
let iter = iter.into_iter();
let iter = UnsortedDisjoint::new(iter);
for range in iter {
self.internal_add(range);
}
}
}
impl<T: Integer> Ord for RangeSetBlaze<T> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
let mut a = self.ranges();
let mut b = other.ranges();
let mut a_rx = a.next();
let mut b_rx = b.next();
loop {
match (a_rx, b_rx) {
(Some(a_r), Some(b_r)) => {
let cmp_start = a_r.start().cmp(b_r.start());
if cmp_start != Ordering::Equal {
return cmp_start;
}
let cmp_end = a_r.end().cmp(b_r.end());
match cmp_end {
Ordering::Equal => {
a_rx = a.next();
b_rx = b.next();
}
Ordering::Less => {
a_rx = a.next();
b_rx = Some((*a_r.end()).add_one()..=*b_r.end());
}
Ordering::Greater => {
a_rx = Some((*b_r.end()).add_one()..=*a_r.end());
b_rx = b.next();
}
}
}
(Some(_), None) => return Ordering::Greater,
(None, Some(_)) => return Ordering::Less,
(None, None) => return Ordering::Equal,
}
}
}
}
impl<T: Integer> PartialOrd for RangeSetBlaze<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T: Integer> Eq for RangeSetBlaze<T> {}
#[allow(clippy::redundant_pub_crate)]
#[inline]
pub(crate) fn extract_range<T: Integer, R>(range: R) -> (T, T)
where
R: RangeBounds<T>,
{
let start = match range.start_bound() {
Bound::Included(n) => *n,
Bound::Excluded(n) => {
assert!(
*n < T::max_value(),
"inclusive start must be <= T::max_safe_value()"
);
n.add_one()
}
Bound::Unbounded => T::min_value(),
};
let end = match range.end_bound() {
Bound::Included(n) => *n,
Bound::Excluded(n) => {
assert!(
*n > T::min_value(),
"inclusive end must be >= T::min_value()"
);
n.sub_one()
}
Bound::Unbounded => T::max_value(),
};
(start, end)
}