use crate::numeric::Domain;
use crate::Interval;
pub trait Merged<Rhs = Self> {
type Output;
fn merged(&self, rhs: &Rhs) -> Option<Self::Output>;
}
impl<T: Domain> Merged<Self> for Interval<T> {
type Output = Self;
fn merged(&self, rhs: &Self) -> Option<Self::Output> {
self.0.merged(&rhs.0).map(|v| v.into())
}
}
#[cfg(test)]
mod tests {
use crate::ops::Complement;
use super::*;
#[quickcheck]
fn check_merge_half_complements_f32(x: f32) {
if x.is_nan() {
return;
}
let x = Interval::unbound_closed(x);
let y = x.complement().intervals()[0].clone();
assert_eq!(x.merged(&y).unwrap(), Interval::unbounded());
}
#[quickcheck]
fn check_merge_half_complements_i32(x: i32) {
let x = Interval::closed_unbound(x);
let y = x.complement().intervals()[0].clone();
assert_eq!(x.merged(&y).unwrap(), Interval::unbounded());
}
#[test]
fn test_merged_max_i32() {
let x = Interval::closed(0, i32::MAX);
let y = Interval::closed(-100, -1);
assert_eq!(x.merged(&y).unwrap(), Interval::closed(-100, i32::MAX));
}
}
#[cfg(feature = "rust_decimal")]
#[cfg(test)]
mod decimal_test {
use super::*;
use crate::MaybeEmpty;
use rust_decimal::Decimal;
#[quickcheck]
fn check_decimal_merge(a: f32, b: f32, c: f32) {
let a = Decimal::from_f32_retain(a);
let b = Decimal::from_f32_retain(b);
let c = Decimal::from_f32_retain(c);
if a.is_none() || b.is_none() || c.is_none() {
return;
}
let a = a.unwrap();
let b = b.unwrap();
let c = c.unwrap();
let left = Interval::open(a.clone(), b.clone());
let right = Interval::closed(b.clone(), c.clone());
let merged = left.merged(&right).unwrap();
if left.is_empty() {
assert_eq!(merged, right);
} else if right.is_empty() {
assert_eq!(merged, left);
} else {
assert_eq!(
left.merged(&right).unwrap(),
Interval::open_closed(a.clone(), c.clone())
);
}
}
}