use crate::{
traits::{ChromBounds, ValueBounds},
Coordinates, Overlap,
};
pub trait Distance<C, T>: Coordinates<C, T> + Overlap<C, T>
where
C: ChromBounds,
T: ValueBounds,
{
fn distance<I: Coordinates<C, T>>(&self, other: &I) -> Option<T> {
if self.overlaps(other) || self.borders(other) {
Some(T::zero())
} else if self.chr() != other.chr() {
None
} else if self.gt(other) {
Some(self.start() - other.end())
} else {
Some(other.start() - self.end())
}
}
fn directed_distance<I: Coordinates<C, T>>(&self, other: &I) -> Option<isize> {
if self.overlaps(other) || self.borders(other) {
Some(0)
} else if self.chr() != other.chr() {
None
} else if self.gt(other) {
(self.start() - other.end()).to_isize().map(|x| -x)
} else {
(other.start() - self.end()).to_isize()
}
}
}
#[cfg(test)]
#[allow(clippy::doc_markdown)]
mod testing {
use crate::{traits::interval::Distance, BaseInterval, Bed3};
#[test]
fn distance_a() {
let a = BaseInterval::new(10, 20);
let b = BaseInterval::new(15, 25);
assert_eq!(a.distance(&b), Some(0));
}
#[test]
fn distance_b() {
let a = BaseInterval::new(10, 20);
let b = BaseInterval::new(20, 30);
assert_eq!(a.distance(&b), Some(0));
}
#[test]
fn distance_c() {
let a = BaseInterval::new(10, 20);
let b = BaseInterval::new(21, 30);
assert_eq!(a.distance(&b), Some(1));
}
#[test]
fn distance_d() {
let a = BaseInterval::new(21, 30);
let b = BaseInterval::new(10, 20);
assert_eq!(a.distance(&b), Some(1));
}
#[test]
fn distance_e() {
let a = Bed3::new(1, 21, 30);
let b = Bed3::new(1, 10, 20);
assert_eq!(a.distance(&b), Some(1));
}
#[test]
fn distance_f() {
let a = Bed3::new(2, 21, 30);
let b = Bed3::new(1, 10, 20);
assert_eq!(a.distance(&b), None);
}
#[test]
fn distance_g() {
let a = Bed3::new(1, 10, 20);
let b = Bed3::new(2, 21, 30);
assert_eq!(a.distance(&b), None);
}
#[test]
fn distance_h() {
let a = Bed3::new(2, 10, 20);
let b = Bed3::new(1, 21, 30);
assert_eq!(a.distance(&b), None);
}
#[test]
fn distance_i() {
let a = Bed3::new(2, 21, 30);
let b = Bed3::new(1, 10, 20);
assert_eq!(a.distance(&b), None);
}
#[test]
fn directed_distance_a() {
let a = BaseInterval::new(10, 20);
let b = BaseInterval::new(15, 25);
assert_eq!(a.directed_distance(&b), Some(0));
}
#[test]
fn directed_distance_b() {
let a = BaseInterval::new(10, 20);
let b = BaseInterval::new(20, 30);
assert_eq!(a.directed_distance(&b), Some(0));
}
#[test]
fn directed_distance_c() {
let a = BaseInterval::new(10, 20);
let b = BaseInterval::new(21, 30);
assert_eq!(a.directed_distance(&b), Some(1));
}
#[test]
fn directed_distance_d() {
let a = BaseInterval::new(21, 30);
let b = BaseInterval::new(10, 20);
assert_eq!(a.directed_distance(&b), Some(-1));
}
#[test]
fn directed_distance_e() {
let a = Bed3::new(2, 21, 30);
let b = Bed3::new(1, 10, 20);
assert_eq!(a.directed_distance(&b), None);
}
#[test]
fn directed_distance_f() {
let a = Bed3::new(1, 10, 20);
let b = Bed3::new(2, 21, 30);
assert_eq!(a.directed_distance(&b), None);
}
#[test]
fn directed_distance_g() {
let a = Bed3::new(2, 10, 20);
let b = Bed3::new(1, 21, 30);
assert_eq!(a.directed_distance(&b), None);
}
#[test]
fn directed_distance_h() {
let a = Bed3::new(2, 21, 30);
let b = Bed3::new(1, 10, 20);
assert_eq!(a.directed_distance(&b), None);
}
}