private static int?Compare(T left, Bound <T> right) { switch (right._type) { case BoundType.NegativeInfinity: return(1); case BoundType.PositiveInfinity: return(-1); case BoundType.Closed: return(left.CompareTo((T)right)); default: { int cmp = left.CompareTo((T)right); return(cmp == 0 ? (int?)null : cmp); } } }
private static void CheckBounds(Bound <T> lowerBound, Bound <T> upperBound) { if (lowerBound == null || upperBound == null) { throw new ArgumentException("Bounds cannot be null."); } if (lowerBound.IsPositiveInfinity()) { throw new ArgumentException("Lower bound cannot be positive infinity."); } if (upperBound.IsNegativeInfinity()) { throw new ArgumentException("Upper bound cannot be negative infinity."); } if (!lowerBound.IsNegativeInfinity() && (T)lowerBound > upperBound || !upperBound.IsPositiveInfinity() && lowerBound > (T)upperBound) { throw new ArgumentException("Lower bound must be <= upper bound."); } }
private static List <Interval <T> > SingleIntervalComplement <T>(Interval <T> interval) where T : IComparable { if (interval.IsEmpty()) { return(new List <Interval <T> > { Interval <T> .FromBounds(Bound <T> .NegativeInfinity(), Bound <T> .PositiveInfinity()) }); } if (interval.LowerBound.IsNegativeInfinity()) { if (interval.UpperBound.IsPositiveInfinity()) { return(new List <Interval <T> > { Interval <T> .Empty() }); } return(new List <Interval <T> > { UpperUnbounded() }); } if (interval.UpperBound.IsPositiveInfinity()) { return(new List <Interval <T> > { LowerUnbounded() }); } return(new List <Interval <T> > { LowerUnbounded(), UpperUnbounded() }); // Local functions Interval <T> UpperUnbounded() { return(Interval <T> .FromBounds(interval.UpperBound.IsOpen() ?Bound <T> .Closed(interval.UpperBound) : Bound <T> .Open(interval.UpperBound), Bound <T> .PositiveInfinity())); } Interval <T> LowerUnbounded() { return(Interval <T> .FromBounds(Bound <T> .NegativeInfinity(), interval.LowerBound.IsOpen() ?Bound <T> .Closed(interval.LowerBound) : Bound <T> .Open(interval.LowerBound))); } }
/// <summary> /// Two bounds are considered equal if their type (open, closed) and their values are equal. infinity bounds /// are always considered not equal. /// </summary> /// <param name="other"></param> /// <returns></returns> public bool Equals(Bound <T> other) { return(_type != BoundType.PositiveInfinity && _type != BoundType.NegativeInfinity && EqualityComparer <T> .Default.Equals(_value, other._value) && _type == other._type); }
/// <summary> /// Creates an interval given its bounds. /// </summary> /// <param name="lowerBound">The lower bound.</param> /// <param name="upperBound">The upper bound.</param> /// <returns>The newly created interval.</returns> public static Interval <T> FromBounds(Bound <T> lowerBound, Bound <T> upperBound) { return(lowerBound == upperBound && (lowerBound.IsOpen() || upperBound.IsOpen()) ? new EmptyInterval <T>() : new Interval <T>(lowerBound, upperBound)); }
/// <summary> /// Creates an interval with a closed lower bound and an open upper bound. /// </summary> /// <param name="lowerBound">The lower bound.</param> /// <param name="upperBound">The upper bound.</param> public static Interval <T> ClosedOpen(T lowerBound, T upperBound) { return(FromBounds(Bound <T> .Closed(lowerBound), Bound <T> .Open(upperBound))); }
/// <summary> /// Creates an interval given its bounds. /// </summary> /// <param name="lowerBound">The lower bound.</param> /// <param name="upperBound">The upper bound.</param> private Interval(Bound <T> lowerBound, Bound <T> upperBound) { CheckBounds(lowerBound, upperBound); LowerBound = lowerBound; UpperBound = upperBound; }