using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary; using System.Diagnostics; using System.ComponentModel; using Microsoft.Research.DynamicDataDisplay.Common; namespace Microsoft.Research.DynamicDataDisplay.Charts { /// /// An ordered pair of values, representing a segment. /// /// Type of each of two values of range. [Serializable] [DebuggerDisplay(@"{Min} — {Max}")] [TypeConverter(typeof(RangeConverter))] public struct Range : IEquatable> { /// /// Initializes a new instance of the struct. /// /// The minimal value of segment. /// The maximal value of segment. public Range(T min, T max) { this.min = min; this.max = max; #if DEBUG if (min is IComparable) { IComparable c1 = (IComparable)min; IComparable c2 = (IComparable)max; DebugVerify.Is(c1.CompareTo(c2) <= 0); } #endif } private readonly T min; /// /// Gets the minimal value of segment. /// /// The min. public T Min { get { return min; } } private readonly T max; /// /// Gets the maximal value of segment. /// /// The max. public T Max { get { return max; } } static float floatEps = (float)1e-10; static double doubleEps = 1e-10; public static bool operator ==(Range first, Range second) { return (first.min.Equals(second.min) && first.max.Equals(second.max) || first.IsEmpty && second.IsEmpty); } public static bool operator !=(Range first, Range second) { return !(first == second); } public static bool operator <(Range first, Range second) { IComparable firstMin = first.min as IComparable; if (firstMin == null) throw new InvalidOperationException("Cannot compare ranges which are not IComparable."); IComparable firstMax = first.max as IComparable; return firstMin.CompareTo(second.Min) > 0 && firstMax.CompareTo(second.Max) < 0; } public static bool operator >(Range first, Range second) { IComparable firstMin = first.min as IComparable; if (firstMin == null) throw new InvalidOperationException("Cannot compare ranges which are not IComparable."); IComparable firstMax = first.max as IComparable; return firstMin.CompareTo(second.min) < 0 && firstMax.CompareTo(second.max) > 0; } public static bool EqualEps(Range first, Range second, double eps) { double delta = Math.Min(first.GetLength(), second.GetLength()); return Math.Abs(first.Min - second.Min) < eps * delta && Math.Abs(first.Max - second.Max) < eps * delta; } /// /// Indicates whether this instance and a specified object are equal. /// /// Another object to compare to. /// /// true if and this instance are the same type and represent the same value; otherwise, false. /// public override bool Equals(object obj) { if (obj is Range) { Range other = (Range)obj; return (min.Equals(other.min) && max.Equals(other.max) || IsEmpty && other.IsEmpty); } else return false; } /// /// Returns the hash code for this instance. /// /// /// A 32-bit signed integer that is the hash code for this instance. /// public override int GetHashCode() { return min.GetHashCode() ^ max.GetHashCode(); } /// /// Returns the fully qualified type name of this instance. /// /// /// A containing a fully qualified type name. /// public override string ToString() { return String.Format("{0} — {1}", min, max); } /// /// Gets a value indicating whether this range is empty. /// /// true if this instance is empty; otherwise, false. public bool IsEmpty { get { if (typeof(T) is IComparable) return ((IComparable)min).CompareTo(max) >= 0; else return min.Equals(max); } } /// /// Indicates whether the current object is equal to another object of the same type. /// /// An object to compare with this object. /// /// true if the current object is equal to the parameter; otherwise, false. /// public bool Equals(Range other) { return this == other; } } }