Generic Interval and IntervalSet algebra crate
-
This crate is pure generic interval algebra, and can be implemented for any type
-
main-types :
intervalx::interval::Interval<T:Ord+IntervalBound>intervalx::set::IntervalSet<T:Ord+IntervalBound>
-
Mathematically correct interval types: open, closed, left_open, right_open, point, empty, and unbounded.
-
Generic over numeric types: Works out-of-the-box with standard primitives (i32, i64, u32, u64, f32, f64).
-
Extensible via
IntervalBoundtrait: Allows users to define intervals for custom numeric types, units, or domain-specific numbers. -
Safe empty interval handling: Automatically handles degenerate intervals like
(5,5). -
Unbounded intervals: Represent full numeric ranges using practical finite bounds (MIN/MAX) of the user-implemented type for real-world safety, in other words
[-Inf,+inf] intervalfori32is actually[i32::MIN,i32::MAX]as implemented for default. -
Contains checks: Easily test if a value is inside an interval *with
.contains(&x). -
Algebraic operations: Supports intersect, union, overlaps, and adjacency checks (planned for advanced versions).
-
Beginner-friendly defaults: Use immediately with standard numeric types; no trait implementation required.
-
Advanced usage: Fully generic and type-safe for experts needing custom types or unit-safe intervals.
-
Readable algebraic notation: Intervals are displayed in standard mathematical forms
(a,b),[a,b],(a,b],[a,b).
-
intervalx::interval::IntervalBoundTrait andstd::cmp::OrdTrait must be implemented for any type that want to useInterval<T> -
default implementation of
IntervalBoundis supplied fori8,i16,i32,i64,i128,u8,u16,u32,u64,u128. -
intervalx::bound::Bound(Open(x))excludes x -
intervalx::bound::Bound(Closed(x))includes x
- Basic usage:
use intervalx::interval::*;
let open_interval=Interval::open(5, 7);//only 6 inside ,represented algebric: (5,7)
println!("{}",open_interval);
assert!(open_interval.contains(&6));
let closed_interval=Interval::closed(5, 6);//contains 5 and 6 ,represented algebric: [5,6]
println!("{}",closed_interval);
assert!(closed_interval.contains(&5));
assert!(closed_interval.contains(&6));
let left_open=Interval::left_open(5, 6);//contains only 6 represented algebric: (5,6]
println!("{}",left_open);
assert!(left_open.contains(&6));
assert!(!left_open.contains(&5));
let right_open=Interval::right_open(5, 6);//contains only 5,represented algebric: [5,6)
println!("{}",right_open);
assert!(right_open.contains(&5));
assert!(!right_open.contains(&6));
let unbounded=Interval::unbounded();//contains all the elements as [MIN,MAX],represented algebric: [MIN,MAX]
println!("{}",unbounded);
for i in -50..=50 {
assert!(unbounded.contains(&i))
}
let empty_interval:Interval<i32>=Interval::empty();
println!("{}",empty_interval);
let empty_interval1=Interval::open(5, 5);//(5,5) open is empty interval
println!("{}",empty_interval1);
//in fact any Open Interval (one side,or two sides) that the endpoints are equal results in empty interval,
//..
let empty_interval2=Interval::left_open(5, 5);//(5,5] left open is empty interval
println!("{}",empty_interval2);
for i in -50..=50{
assert!(!empty_interval.contains(&i));
assert!(!empty_interval1.contains(&i));
assert!(!empty_interval2.contains(&i));
}- basic methods
use intervalx::interval::*;
let a_b=Interval::closed(-1, 1);
let c_d=Interval::closed(1, 3);
let a_b_intersects_c_d=a_b.intersection(&c_d);
println!("{}",a_b_intersects_c_d);
assert!(a_b_intersects_c_d.contains(&1));
let inf_=Interval::left_open(1,i64::MAX);
println!("{}",inf_);
let open1=Interval::open(-1, 5);
let b=Interval::open(-1, 4);
let isn=open1.intersection(&b);
println!("isn: {}",isn);
assert!(!isn.contains(&5));
println!("#########################");
let a = Interval::closed(9, 10);//(0,5)
let b = Interval::closed(1, 8);//[5,8]
let i = a.intersection(&b);
println!("intersection: {}",i);
let a = Interval::closed(1, 2);
let b = Interval::closed(2, 3);
let i=a.intersection(&b);
println!("{}",i);
let a=Interval::open(1, 5);
let b=Interval::closed(1, 5);
let i=a.intersection(&b);
println!("I: {}",i);
let age_interval=Interval::closed(HumanAge::min_limit(), HumanAge::max_limit());
println!("age-interval : {}",age_interval);
let ossama_age=HumanAge{ age:31 };
assert!(age_interval.contains(&ossama_age));
let a:Interval<i32>=Interval::unbounded();
let b=Interval::unbounded();
let i=a.intersection(&b);
println!("bounded ∩ open : {i}");
let a=Interval::right_open(1, 3);
let b=Interval::closed(3, 5);
println!("{}",a.intersection(&b));
let a=Interval::right_open(1, 3);
let b=Interval::closed(3, 5);
println!("{}",a.is_adjacent(&b));
use std::fmt::{Debug, Display};
use intervalx::interval::*;
use intervalx::set::*;
#[derive(PartialEq, Clone, Eq, PartialOrd, Ord, Debug)]
struct NetworkPort(u16);
impl IntervalBound for NetworkPort {
fn min_limit() -> Self {
NetworkPort(0)
}
fn max_limit() -> Self {
NetworkPort(65535)
}
}
impl Display for NetworkPort {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f,"port({})",&self.0)
}
}
fn main(){
let port_interval:Interval<NetworkPort>=Interval::unbounded();
println!("{}",port_interval);
//output -> unbounded-interval [MIN,MAX]: [port(0),port(65535)]
//Note that , MIN,MAX are related to NetworkPort Structure.
let port_8080=NetworkPort(8080);
assert!(port_interval.contains(&port_8080));
}