/// <summary> /// Compares this instance to a specified <see cref="Bound<T>"/> and returns an indication of their relative values. /// </summary> /// <param name="other">A <see cref="Bound<T>"/> to compare to this instance.</param> /// <returns> /// A signed number indicating the relative values of this instance and the <paramref name="other"/>. /// <list type="table"> /// <listheader> /// <term>Value Type</term> /// <description>Condition</description> /// </listheader> /// <item> /// <term>Less than zero</term> /// <description>This instance is less than the <paramref name="other"/>.</description> /// </item> /// <item> /// <term>Zero</term> /// <description>This instance is equal to the <paramref name="other"/>.</description> /// </item> /// <item> /// <term>Greater than zero</term> /// <description>This instance is greater than the <paramref name="other"/>.</description> /// </item> ///</list> /// </returns> /// <exception cref="ArgumentNullException"><paramref name="other"/> is null.</exception> public int CompareTo(Bound <T> other) { if (other == null) { throw new ArgumentNullException("other"); } //perform value comparaison var vCompare = ((Type == BoundType.Upper && Bound.IsInfinity(Value)) || (other.Type == BoundType.Upper && Bound.IsInfinity(other.Value))) ? Comparer <T> .Default.Compare(other.Value, Value) : Comparer <T> .Default.Compare(Value, other.Value); //consider value comparaison if (vCompare != 0) { return(vCompare); } else { //perform type comparaison var tCompare = Type.CompareTo(other.Type); if (tCompare != 0) { return(tCompare); } else { //perform direction comparaison return((Type == BoundType.Upper) ? Direction.CompareTo(other.Direction) : other.Direction.CompareTo(Direction)); } } }
/// <summary> /// Determines whether an <see cref="Interval<T>"/> contains a specified <paramref name="value"/>. /// </summary> /// <typeparam name="T">The value type of the interval.</typeparam> /// <param name="interval">An <see cref="Interval<T>"/> reference.</param> /// <param name="value">The value to search for.</param> /// <returns> /// <c>true</c> if the <paramref name="interval"/> contains the <paramref name="value"/>; otherwise, <c>false</c>. /// </returns> public static bool Contains <T>(Interval <T> interval, T value) { if (IsNullOrEmpty(interval)) { return(false); } var lowerBound = interval.LowerBound; var upperBound = interval.UpperBound; if (Bound.IsInfinity(value)) { //consider [null ; null[ OR ]null ; null] cases if (object.Equals(lowerBound.Value, upperBound.Value) && Bound.IsInfinity(lowerBound.Value) && lowerBound.Direction != upperBound.Direction) { return(false); } else { return((lowerBound.Direction == BoundDirection.Closed && Comparer <T> .Default.Compare(lowerBound.Value, value) == 0) || (upperBound.Direction == BoundDirection.Closed && Comparer <T> .Default.Compare(upperBound.Value, value) == 0)); } } else { return(lowerBound.Contains(value) && upperBound.Contains(value)); } }
/// <summary> /// Gets a value indicating whether this instance represents a singleton of the specified element. /// </summary> /// <param name="value">The element value.</param> /// <returns> /// <c>true</c> if this instance contains only the specified <paramref name="value"/>; otherwise, <c>false</c>. /// </returns> /// <seealso cref="IsSingleton"/> /// <seealso cref="Interval.SingletonOf"/> /// <seealso href="http://en.wikipedia.org/wiki/Singleton_(mathematics)">Singleton (mathematics)</seealso> public bool IsSingletonOf(T value) { return(object.Equals(LowerBound.Value, value) && object.Equals(UpperBound.Value, value) && object.Equals(LowerBound.Direction, BoundDirection.Closed) && object.Equals(UpperBound.Direction, BoundDirection.Closed) && !Bound.IsInfinity(LowerBound.Value)); }
/// <summary> /// Gets a value indicating whether this instance represents an empty <see cref="Interval<T>"/> of the specified element. /// </summary> /// <param name="value">The element value.</param> /// <returns> /// <c>true</c> if this instance contains no element; otherwise, <c>false</c>. /// </returns> /// <seealso cref="IsEmpty"/> /// <seealso cref="Empty"/> /// <seealso cref="Interval.EmptyOf"/> /// <seealso href="http://en.wikipedia.org/wiki/Empty_set">Empty Set (set theory)</seealso> protected internal bool IsEmptyOf(T value) { return(object.Equals(LowerBound.Value, value) && object.Equals(UpperBound.Value, value) && object.Equals(LowerBound.Direction, UpperBound.Direction) && (Bound.IsInfinity(LowerBound.Value) ? object.Equals(LowerBound.Direction, BoundDirection.Closed) : object.Equals(LowerBound.Direction, BoundDirection.Opened))); }
internal Bound(BoundType type, BoundDirection direction, T value, bool checkArguments) { if (checkArguments && Bound.IsInfinity(value) && direction == BoundDirection.Closed) { throw new ArgumentException("An infinity bound must define an opened direction."); } Type = type; Direction = direction; Value = value; }
internal static bool TryParse <T>(BoundType type , BoundDirection direction , T value , out Bound <T> result) { result = (Bound.IsInfinity(value) && direction == BoundDirection.Closed) ? default(Bound <T>) : new Bound <T>(type, direction, value); return(result != default(Bound <T>)); }
/// <summary> /// Gets a singleton of the specified element. /// </summary> /// <typeparam name="T">The value type of the intervals.</typeparam> /// <param name="value">The element value.</param> /// <returns> /// An <see cref="Interval<T>"/> containing only the specified <paramref name="value"/>. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="value"/> is null.</exception> /// <seealso cref="Interval<T>.IsSingleton"/> /// <seealso cref="Interval<T>.IsSingletonOf"/> /// <seealso href="http://en.wikipedia.org/wiki/Singleton_(mathematics)">Singleton (mathematics)</seealso> public static Interval <T> SingletonOf <T>(T value) { if (Bound.IsInfinity(value)) { throw new ArgumentNullException("value"); } return(new Interval <T>(BoundDirection.Closed , value , value , BoundDirection.Closed)); }
/// <summary> /// Gets an empty <see cref="Interval<T>"/> of the specified element. /// </summary> /// <typeparam name="T">The value type of the intervals.</typeparam> /// <param name="value">The element value.</param> /// <returns> /// An interval <see cref="Interval<T>"/> containing no element. /// </returns> /// <remarks> /// An empty <see cref="Interval<T>"/> is composed of one element /// (usually <c>default(T)</c> but not exclusively) /// with <see cref="BoundDirection.Opened"/> boundaries; /// except when <typeparamref name="T"/> represents a reference type, /// the default empty interval is composed of <see cref="BoundDirection.Closed"/> boundaries. /// It enables the distinction between the default <see cref="Empty"/> interval and /// the <see cref="Universe"/> interval. /// </remarks> /// <seealso cref="Empty"/> /// <seealso cref="Interval<T>.IsEmpty"/> /// <seealso cref="Interval<T>.IsEmptyOf"/> /// <seealso href="http://en.wikipedia.org/wiki/Empty_set">Empty Set (set theory)</seealso> internal static Interval <T> EmptyOf <T>(T value) { return(Bound.IsInfinity(value) ? new Interval <T>(BoundDirection.Closed , value , value , BoundDirection.Closed) : new Interval <T>(BoundDirection.Opened , value , value , BoundDirection.Opened)); }
internal int UnionCompareTo(Bound <T> other) { //perform value comparaison var vCompare = ((Type == BoundType.Upper && Bound.IsInfinity(Value)) || (other.Type == BoundType.Upper && Bound.IsInfinity(other.Value))) ? Comparer <T> .Default.Compare(other.Value, Value) : Comparer <T> .Default.Compare(Value, other.Value); return((vCompare != 0) ? vCompare : (object.Equals(Direction, BoundDirection.Closed) || object.Equals(other.Direction, BoundDirection.Closed)) ? 0 : -1); }
internal bool Contains(T value) { return(Type == BoundType.Lower ? Direction == BoundDirection.Closed ? Comparer <T> .Default.Compare(Value, value) <= 0 : Comparer <T> .Default.Compare(Value, value) < 0 : Direction == BoundDirection.Closed ? Bound.IsInfinity(Value) ? Comparer <T> .Default.Compare(value, Value) >= 0 : Comparer <T> .Default.Compare(Value, value) >= 0 : Bound.IsInfinity(Value) ? Comparer <T> .Default.Compare(value, Value) > 0 : Comparer <T> .Default.Compare(Value, value) > 0); }
/// <summary> /// Initializes a new instance of the <see cref="Interval<T>"/> class. /// </summary> /// <param name="lowerBound">The lower bound.</param> /// <param name="upperBound">The upper bound.</param> protected internal Interval(Bound <T> lowerBound , Bound <T> upperBound) { if (lowerBound == null || upperBound == null) { throw new ArgumentNullException("lowerBound or upperBound"); } if (lowerBound > upperBound) { throw new ArgumentException("The lower bound must be lower than or equal the upper bound."); } if (object.Equals(lowerBound.Value, upperBound.Value) && !object.Equals(lowerBound.Direction, upperBound.Direction) && !Bound.IsInfinity(lowerBound.Value)) { throw new ArgumentException("Singleton or empty interval must define the same boundary direction."); } LowerBound = lowerBound; UpperBound = upperBound; }
internal static bool TryParse <T>(Bound <T> lowerBound , Bound <T> upperBound , out Interval <T> result) { result = default(Interval <T>); if (lowerBound == null || upperBound == null || lowerBound > upperBound) { return(false); } if (object.Equals(lowerBound.Value, upperBound.Value) && !object.Equals(lowerBound.Direction, upperBound.Direction) && !Bound.IsInfinity(lowerBound.Value)) { return(false); } result = new Interval <T>(lowerBound, upperBound); return(true); }