extern crate num_traits;
extern crate smallvec;
pub mod range_compare;
pub use range_compare::{
RangeCompare, RangeDisjoint, RangeIntersect,
range_compare, intersection, is_empty
};
use num_traits::PrimInt;
#[derive(Clone,Debug,Eq,PartialEq)]
pub struct RangeSet <A> where
A : smallvec::Array + Eq + std::fmt::Debug,
A::Item : Clone + Eq + std::fmt::Debug
{
ranges : smallvec::SmallVec <A>
}
pub struct Iter <'a, A, T> where
A : 'a + smallvec::Array <Item=std::ops::RangeInclusive <T>>
+ Eq + std::fmt::Debug,
T : 'a + PrimInt + std::fmt::Debug
{
range_set : &'a RangeSet <A>,
range_index : usize,
range : std::ops::RangeInclusive <T>
}
pub fn report_sizes() {
use std::ops::RangeInclusive;
println!("RangeSet report sizes...");
println!(" size of RangeSet <[RangeInclusive <u32>; 1]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u32>; 1]>>());
println!(" size of RangeSet <[RangeInclusive <u16>; 1]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u16>; 1]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 1]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u32>; 1]>>());
println!(" size of RangeSet <[RangeInclusive <u64>; 1]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u64>; 1]>>());
println!(" size of RangeSet <[RangeInclusive <usize>; 1]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <usize>; 1]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 2]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u32>; 2]>>());
println!(" size of RangeSet <[RangeInclusive <u16>; 2]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u16>; 2]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 2]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u32>; 2]>>());
println!(" size of RangeSet <[RangeInclusive <u64>; 2]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u64>; 2]>>());
println!(" size of RangeSet <[RangeInclusive <usize>; 2]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <usize>; 2]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 4]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u32>; 4]>>());
println!(" size of RangeSet <[RangeInclusive <u16>; 4]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u16>; 4]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 4]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u32>; 4]>>());
println!(" size of RangeSet <[RangeInclusive <u64>; 4]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u64>; 4]>>());
println!(" size of RangeSet <[RangeInclusive <usize>; 4]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <usize>; 4]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 8]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u32>; 8]>>());
println!(" size of RangeSet <[RangeInclusive <u16>; 8]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u16>; 8]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 8]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u32>; 8]>>());
println!(" size of RangeSet <[RangeInclusive <u64>; 8]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u64>; 8]>>());
println!(" size of RangeSet <[RangeInclusive <usize>; 8]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <usize>; 8]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 16]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u32>; 16]>>());
println!(" size of RangeSet <[RangeInclusive <u16>; 16]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u16>; 16]>>());
println!(" size of RangeSet <[RangeInclusive <u32>; 16]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u32>; 16]>>());
println!(" size of RangeSet <[RangeInclusive <u64>; 16]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <u64>; 16]>>());
println!(" size of RangeSet <[RangeInclusive <usize>; 16]>: {}",
std::mem::size_of::<RangeSet <[RangeInclusive <usize>; 16]>>());
println!("...RangeSet report sizes");
}
impl <A, T> RangeSet <A> where
A : smallvec::Array <Item=std::ops::RangeInclusive <T>>
+ Eq + std::fmt::Debug,
T : PrimInt + std::fmt::Debug
{
#[inline]
pub fn new() -> Self {
RangeSet {
ranges: smallvec::SmallVec::new()
}
}
#[inline]
pub fn with_capacity (capacity : usize) -> Self {
RangeSet {
ranges: smallvec::SmallVec::with_capacity (capacity)
}
}
#[inline]
pub fn from_ranges (ranges : smallvec::SmallVec <A>) -> Option <Self> {
if Self::valid_range_vec (&ranges) {
Some (RangeSet { ranges })
} else {
None
}
}
#[inline]
pub fn is_empty (&self) -> bool {
self.ranges.is_empty()
}
#[inline]
pub fn clear (&mut self) {
self.ranges.clear()
}
#[inline]
pub fn into_smallvec (self) -> smallvec::SmallVec <A> {
self.ranges
}
pub fn insert (&mut self, element : T) -> bool {
if let Some (_) = self.insert_range (element..=element) {
false
} else {
true
}
}
pub fn remove (&mut self, element : T) -> bool {
if let Some (_) = self.remove_range (element..=element) {
true
} else {
false
}
}
pub fn insert_range (&mut self, range : A::Item) -> Option <Self> {
if is_empty (&range) {
return None
}
if self.ranges.is_empty() {
self.ranges.push (range);
return None
}
let before = Self::binary_search_before_proper (self, &range);
let after = Self::binary_search_after_proper (self, &range);
match (before, after) {
(None, None) => {
let isect = self.range_intersection (&range, 0..self.ranges.len());
let new_range =
std::cmp::min (*range.start(), *self.ranges[0].start())..=
std::cmp::max (*range.end(), *self.ranges[self.ranges.len()-1].end());
self.ranges.clear();
self.ranges.push (new_range);
if !isect.is_empty() {
Some (isect)
} else {
None
}
}
(Some (before), None) => {
if before+1 == self.ranges.len() {
self.ranges.push (range);
None
} else {
let isect
= self.range_intersection (&range, before+1..self.ranges.len());
self.ranges[before+1] =
std::cmp::min (*range.start(), *self.ranges[before+1].start())..=
std::cmp::max (*range.end(), *self.ranges[self.ranges.len()-1].end());
self.ranges.truncate (before+2);
if !isect.is_empty() {
Some (isect)
} else {
None
}
}
}
(None, Some (after)) => {
if after == 0 {
self.ranges.insert (0, range);
None
} else {
let isect = self.range_intersection (&range, 0..after);
self.ranges[0] =
std::cmp::min (*range.start(), *self.ranges[0].start())..=
std::cmp::max (*range.end(), *self.ranges[after-1].end());
for i in 0..after {
self.ranges[i+1] = self.ranges[after + i].clone();
}
let new_len = self.ranges.len() - after + 1;
self.ranges.truncate (new_len);
if !isect.is_empty() {
Some (isect)
} else {
None
}
}
}
(Some (before), Some (after)) => {
if before+1 == after {
self.ranges.insert (before+1, range);
None
} else {
let isect = self.range_intersection (&range, before+1..after);
self.ranges[before+1] =
std::cmp::min (*range.start(), *self.ranges[before+1].start())..=
std::cmp::max (*range.end(), *self.ranges[after-1].end());
if 1 < after - before - 1 {
for i in 0..(after-before-1) {
self.ranges[before+1+i] = self.ranges[after + i].clone();
}
let new_len = self.ranges.len() - (after - before - 2);
self.ranges.truncate (new_len);
}
if !isect.is_empty() {
Some (isect)
} else {
None
}
}
}
}
}
pub fn remove_range (&mut self, range : A::Item) -> Option <Self> {
if self.ranges.is_empty() || is_empty (&range) {
return None
}
let before = Self::binary_search_before (self, &range);
let after = Self::binary_search_after (self, &range);
let (isect_first, isect_last) = match (before, after) {
(None, None) => (0, self.ranges.len()),
(Some (before), None) => (before+1, self.ranges.len()),
(None, Some (after)) => (0, after),
(Some (before), Some (after)) => (before+1, after)
};
let isect = self.range_intersection (&range, isect_first..isect_last);
if isect.is_empty() {
return None
}
if isect_last - isect_first == 1 {
let single_range = self.ranges[isect_first].clone();
if single_range.start() < range.start() && range.end() < single_range.end() {
let left = *single_range.start()..=*range.start() - T::one();
let right = *range.end() + T::one()..=*single_range.end();
self.ranges[isect_first] = right;
self.ranges.insert (isect_first, left);
return Some (isect)
}
}
let first = self.ranges[isect_first].clone();
let last = self.ranges[isect_last-1].clone();
let (remove_first, remove_last) = if
range.start() <= first.start() && last.end() <= range.end()
{
(isect_first, isect_last)
} else if first.start() < range.start() && last.end() <= range.end() {
self.ranges[isect_first] = *self.ranges[isect_first].start()..=*range.start() - T::one();
(isect_first+1, isect_last)
} else if range.start() <= first.start() && range.end() < last.end() {
self.ranges[isect_last-1] = *range.end() + T::one()..=*self.ranges[isect_last-1].end();
(isect_first, isect_last-1)
} else {
debug_assert!(first.start() < range.start() && range.end() < last.end());
self.ranges[isect_first] = *self.ranges[isect_first].start()..=*range.start() - T::one();
self.ranges[isect_last-1] = *range.end() + T::one()..=*self.ranges[isect_last-1].end();
(isect_first+1, isect_last-1)
};
for (i, index) in (remove_last..self.ranges.len()).enumerate() {
self.ranges[remove_first+i] = self.ranges[index].clone();
}
let new_len = self.ranges.len() - (remove_last - remove_first);
self.ranges.truncate (new_len);
debug_assert!(self.is_valid());
Some (isect)
}
pub fn iter (&self) -> Iter <A, T> {
Iter {
range_set: self,
range_index: 0,
range: T::one()..=T::zero()
}
}
pub fn valid_range_vec (
ranges : &smallvec::SmallVec <A>
) -> bool {
if !ranges.is_empty() {
for i in 0..ranges.len()-1 {
let this = &ranges[i];
let next = &ranges[i+1];
if is_empty (this) || is_empty (next) {
return false
}
if *next.start() <= *this.end()+T::one() {
return false
}
}
}
true
}
#[inline]
pub fn spilled (&self) -> bool {
self.ranges.spilled()
}
#[inline]
pub fn shrink_to_fit (&mut self) {
self.ranges.shrink_to_fit()
}
fn binary_search_before (&self, range : &A::Item) -> Option <usize> {
let mut before = 0;
let mut after = self.ranges.len();
let mut found = false;
while before != after {
let i = before + (after - before) / 2;
let last = before;
if self.ranges[i].end() < range.start() {
found = true;
before = i;
if before == last {
break
}
} else {
after = i
}
}
if found {
Some (before)
} else {
None
}
}
fn binary_search_after (&self, range : &A::Item) -> Option <usize> {
let mut before = 0;
let mut after = self.ranges.len();
let mut found = false;
while before != after {
let i = before + (after - before) / 2;
let last = before;
if range.end() < self.ranges[i].start() {
found = true;
after = i;
} else {
before = i;
if before == last {
break
}
}
}
if found {
Some (after)
} else {
None
}
}
fn binary_search_before_proper (&self, range : &A::Item) -> Option <usize> {
let mut before = 0;
let mut after = self.ranges.len();
let mut found = false;
while before != after {
let i = before + (after - before) / 2;
let last = before;
if *self.ranges[i].end()+T::one() < *range.start() {
found = true;
before = i;
if before == last {
break
}
} else {
after = i
}
}
if found {
Some (before)
} else {
None
}
}
fn binary_search_after_proper (&self, range : &A::Item) -> Option <usize> {
let mut before = 0;
let mut after = self.ranges.len();
let mut found = false;
while before != after {
let i = before + (after - before) / 2;
let last = before;
if *range.end()+T::one() < *self.ranges[i].start() {
found = true;
after = i;
} else {
before = i;
if before == last {
break
}
}
}
if found {
Some (after)
} else {
None
}
}
fn range_intersection (&self,
range : &A::Item, range_range : std::ops::Range <usize>
) -> Self {
let mut isect = RangeSet::new();
for i in range_range {
let r = &self.ranges[i];
let rsect = intersection (&range, &r);
if !is_empty (&rsect) {
isect.ranges.push (rsect);
}
}
debug_assert!(isect.is_valid());
isect
}
#[inline]
fn is_valid (&self) -> bool {
Self::valid_range_vec (&self.ranges)
}
}
impl <A, T> From <std::ops::RangeInclusive <T>> for RangeSet <A> where
A : smallvec::Array <Item=std::ops::RangeInclusive <T>>
+ Eq + std::fmt::Debug,
T : PrimInt + std::fmt::Debug
{
fn from (range : std::ops::RangeInclusive <T>) -> Self {
let ranges = {
let mut v = smallvec::SmallVec::new();
v.push (range);
v
};
RangeSet { ranges }
}
}
impl <'a, A, T> Iterator for Iter <'a, A, T> where
A : smallvec::Array <Item=std::ops::RangeInclusive <T>>
+ Eq + std::fmt::Debug,
T : PrimInt + std::fmt::Debug,
std::ops::RangeInclusive <T> : Clone + Iterator <Item=T>
{
type Item = T;
fn next (&mut self) -> Option <Self::Item> {
if let Some (t) = self.range.next() {
Some (t)
} else {
if self.range_index < self.range_set.ranges.len() {
self.range = self.range_set.ranges[self.range_index].clone();
debug_assert!(!is_empty (&self.range));
self.range_index += 1;
self.range.next()
} else {
None
}
}
}
}