1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use crate::interval::*;
use std::arch::x86_64::*;

// NOTE: `eq` is implemented in interval.rs

impl Interval {
    pub fn contains(self, rhs: f64) -> bool {
        rhs.is_finite() && self.inf_raw() <= rhs && rhs <= self.sup_raw()
    }

    pub fn disjoint(self, rhs: Self) -> bool {
        self.is_empty()
            || rhs.is_empty()
            || self.sup_raw() < rhs.inf_raw()
            || rhs.sup_raw() < self.inf_raw()
    }

    pub fn interior(self, rhs: Self) -> bool {
        let l = self.is_empty()
            || self.sup_raw() < rhs.sup_raw()
            || self.sup_raw() == f64::INFINITY && rhs.sup_raw() == f64::INFINITY;
        let r = self.is_empty()
            || rhs.inf_raw() < self.inf_raw()
            || rhs.inf_raw() == f64::NEG_INFINITY && self.inf_raw() == f64::NEG_INFINITY;
        l && r
    }

    pub fn is_common_interval(self) -> bool {
        unsafe { _mm_movemask_pd(_mm_cmplt_pd(self.rep, _mm_set1_pd(f64::INFINITY))) == 3 }
    }

    pub fn is_empty(self) -> bool {
        unsafe { _mm_movemask_pd(_mm_cmpunord_pd(self.rep, self.rep)) == 3 }
    }

    pub fn is_entire(self) -> bool {
        unsafe { _mm_movemask_pd(_mm_cmpeq_pd(self.rep, _mm_set1_pd(f64::INFINITY))) == 3 }
    }

    pub fn is_singleton(self) -> bool {
        self.inf_raw() == self.sup_raw()
    }

    pub fn less(self, rhs: Self) -> bool {
        let l = self.is_empty() || self.sup_raw() <= rhs.sup_raw();
        let r = rhs.is_empty() || self.inf_raw() <= rhs.inf_raw();
        l && r
    }

    pub fn precedes(self, rhs: Self) -> bool {
        self.is_empty() || rhs.is_empty() || self.sup_raw() <= rhs.inf_raw()
    }

    pub fn strict_less(self, rhs: Self) -> bool {
        let l = self.is_empty()
            || self.sup_raw() < rhs.sup_raw()
            || self.sup_raw() == f64::INFINITY && rhs.sup_raw() == f64::INFINITY;
        let r = rhs.is_empty()
            || self.inf_raw() < rhs.inf_raw()
            || self.inf_raw() == f64::NEG_INFINITY && rhs.inf_raw() == f64::NEG_INFINITY;
        l && r
    }

    pub fn strict_precedes(self, rhs: Self) -> bool {
        self.is_empty() || rhs.is_empty() || self.sup_raw() < rhs.inf_raw()
    }

    pub fn subset(self, rhs: Self) -> bool {
        self.is_empty() || rhs.inf_raw() <= self.inf_raw() && self.sup_raw() <= rhs.sup_raw()
    }
}

macro_rules! impl_dec {
    ($f:ident, 1) => {
        pub fn $f(self) -> bool {
            if self.is_nai() {
                return false;
            }

            self.x.$f()
        }
    };

    ($f:ident, 2) => {
        pub fn $f(self, rhs: Self) -> bool {
            if self.is_nai() || rhs.is_nai() {
                return false;
            }

            self.x.$f(rhs.x)
        }
    };
}

impl DecoratedInterval {
    pub fn contains(self, rhs: f64) -> bool {
        if self.is_nai() {
            return false;
        }

        Interval::contains(self.x, rhs)
    }

    impl_dec!(disjoint, 2);
    impl_dec!(interior, 2);
    impl_dec!(is_common_interval, 1);
    impl_dec!(is_empty, 1);
    impl_dec!(is_entire, 1);

    pub fn is_nai(self) -> bool {
        self.d == Decoration::Ill
    }

    impl_dec!(is_singleton, 1);
    impl_dec!(less, 2);
    impl_dec!(precedes, 2);
    impl_dec!(strict_less, 2);
    impl_dec!(strict_precedes, 2);
    impl_dec!(subset, 2);
}