Skip to content

Commit 55c08d5

Browse files
berkaysynnadaadriangb
authored andcommitted
minor: add is_superset() method for Interval's (apache#16895)
* Update interval_arithmetic.rs * Update interval_arithmetic.rs * Update interval_arithmetic.rs
1 parent 0caae24 commit 55c08d5

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

datafusion/expr-common/src/interval_arithmetic.rs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,17 @@ impl Interval {
754754
}
755755
}
756756

757+
/// Decide if this interval is a superset of `other`. If argument `strict`
758+
/// is `true`, only returns `true` if this interval is a strict superset.
759+
///
760+
/// NOTE: This function only works with intervals of the same data type.
761+
/// Attempting to compare intervals of different data types will lead
762+
/// to an error.
763+
pub fn is_superset(&self, other: &Interval, strict: bool) -> Result<bool> {
764+
Ok(!(strict && self.eq(other))
765+
&& (self.contains(other)? == Interval::CERTAINLY_TRUE))
766+
}
767+
757768
/// Add the given interval (`other`) to this interval. Say we have intervals
758769
/// `[a1, b1]` and `[a2, b2]`, then their sum is `[a1 + a2, b1 + b2]`. Note
759770
/// that this represents all possible values the sum can take if one can
@@ -3805,4 +3816,138 @@ mod tests {
38053816
let upper = 1.5;
38063817
capture_mode_change_f32((lower, upper), true, true);
38073818
}
3819+
3820+
#[test]
3821+
fn test_is_superset() -> Result<()> {
3822+
// Test cases: (interval1, interval2, strict, expected)
3823+
let test_cases = vec![
3824+
// Equal intervals - non-strict should be true, strict should be false
3825+
(
3826+
Interval::make(Some(10_i32), Some(50_i32))?,
3827+
Interval::make(Some(10_i32), Some(50_i32))?,
3828+
false,
3829+
true,
3830+
),
3831+
(
3832+
Interval::make(Some(10_i32), Some(50_i32))?,
3833+
Interval::make(Some(10_i32), Some(50_i32))?,
3834+
true,
3835+
false,
3836+
),
3837+
// Unbounded intervals
3838+
(
3839+
Interval::make::<i32>(None, None)?,
3840+
Interval::make(Some(10_i32), Some(50_i32))?,
3841+
false,
3842+
true,
3843+
),
3844+
(
3845+
Interval::make::<i32>(None, None)?,
3846+
Interval::make::<i32>(None, None)?,
3847+
false,
3848+
true,
3849+
),
3850+
(
3851+
Interval::make::<i32>(None, None)?,
3852+
Interval::make::<i32>(None, None)?,
3853+
true,
3854+
false,
3855+
),
3856+
// Half-bounded intervals
3857+
(
3858+
Interval::make(Some(0_i32), None)?,
3859+
Interval::make(Some(10_i32), Some(50_i32))?,
3860+
false,
3861+
true,
3862+
),
3863+
(
3864+
Interval::make(None, Some(100_i32))?,
3865+
Interval::make(Some(10_i32), Some(50_i32))?,
3866+
false,
3867+
true,
3868+
),
3869+
// Non-superset cases - partial overlap
3870+
(
3871+
Interval::make(Some(0_i32), Some(50_i32))?,
3872+
Interval::make(Some(25_i32), Some(75_i32))?,
3873+
false,
3874+
false,
3875+
),
3876+
(
3877+
Interval::make(Some(0_i32), Some(50_i32))?,
3878+
Interval::make(Some(25_i32), Some(75_i32))?,
3879+
true,
3880+
false,
3881+
),
3882+
// Non-superset cases - disjoint intervals
3883+
(
3884+
Interval::make(Some(0_i32), Some(50_i32))?,
3885+
Interval::make(Some(60_i32), Some(100_i32))?,
3886+
false,
3887+
false,
3888+
),
3889+
// Subset relationship (reversed)
3890+
(
3891+
Interval::make(Some(20_i32), Some(80_i32))?,
3892+
Interval::make(Some(0_i32), Some(100_i32))?,
3893+
false,
3894+
false,
3895+
),
3896+
// Float cases
3897+
(
3898+
Interval::make(Some(0.0_f32), Some(100.0_f32))?,
3899+
Interval::make(Some(25.5_f32), Some(75.5_f32))?,
3900+
false,
3901+
true,
3902+
),
3903+
(
3904+
Interval::make(Some(0.0_f64), Some(100.0_f64))?,
3905+
Interval::make(Some(0.0_f64), Some(100.0_f64))?,
3906+
true,
3907+
false,
3908+
),
3909+
// Edge cases with single point intervals
3910+
(
3911+
Interval::make(Some(0_i32), Some(100_i32))?,
3912+
Interval::make(Some(50_i32), Some(50_i32))?,
3913+
false,
3914+
true,
3915+
),
3916+
(
3917+
Interval::make(Some(50_i32), Some(50_i32))?,
3918+
Interval::make(Some(50_i32), Some(50_i32))?,
3919+
false,
3920+
true,
3921+
),
3922+
(
3923+
Interval::make(Some(50_i32), Some(50_i32))?,
3924+
Interval::make(Some(50_i32), Some(50_i32))?,
3925+
true,
3926+
false,
3927+
),
3928+
// Boundary touch cases
3929+
(
3930+
Interval::make(Some(0_i32), Some(50_i32))?,
3931+
Interval::make(Some(0_i32), Some(25_i32))?,
3932+
false,
3933+
true,
3934+
),
3935+
(
3936+
Interval::make(Some(0_i32), Some(50_i32))?,
3937+
Interval::make(Some(25_i32), Some(50_i32))?,
3938+
false,
3939+
true,
3940+
),
3941+
];
3942+
3943+
for (interval1, interval2, strict, expected) in test_cases {
3944+
let result = interval1.is_superset(&interval2, strict)?;
3945+
assert_eq!(
3946+
result, expected,
3947+
"Failed for interval1: {interval1}, interval2: {interval2}, strict: {strict}",
3948+
);
3949+
}
3950+
3951+
Ok(())
3952+
}
38083953
}

0 commit comments

Comments
 (0)