/************************************************************************************* Extended WPF Toolkit Copyright (C) 2007-2013 Xceed Software Inc. This program is provided to you under the terms of the Microsoft Public License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license For more features, controls, and fast professional support, pick up the Plus Edition at http://xceed.com/wpf_toolkit Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids ***********************************************************************************/ namespace Standard { using System; using System.Diagnostics.CodeAnalysis; /// /// DoubleUtil uses fixed eps to provide fuzzy comparison functionality for doubles. /// Note that FP noise is a big problem and using any of these compare /// methods is not a complete solution, but rather the way to reduce /// the probability of repeating unnecessary work. /// internal static class DoubleUtilities { /// /// Epsilon - more or less random, more or less small number. /// private const double Epsilon = 0.00000153; /// /// AreClose returns whether or not two doubles are "close". That is, whether or /// not they are within epsilon of each other. /// There are plenty of ways for this to return false even for numbers which /// are theoretically identical, so no code calling this should fail to work if this /// returns false. /// /// The first double to compare. /// The second double to compare. /// The result of the AreClose comparision. [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] public static bool AreClose( double value1, double value2 ) { if( value1 == value2 ) { return true; } double delta = value1 - value2; return ( delta < Epsilon ) && ( delta > -Epsilon ); } /// /// LessThan returns whether or not the first double is less than the second double. /// That is, whether or not the first is strictly less than *and* not within epsilon of /// the other number. /// There are plenty of ways for this to return false even for numbers which /// are theoretically identical, so no code calling this should fail to work if this /// returns false. /// /// The first double to compare. /// The second double to compare. /// The result of the LessThan comparision. [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] public static bool LessThan( double value1, double value2 ) { return ( value1 < value2 ) && !AreClose( value1, value2 ); } /// /// GreaterThan returns whether or not the first double is greater than the second double. /// That is, whether or not the first is strictly greater than *and* not within epsilon of /// the other number. /// There are plenty of ways for this to return false even for numbers which /// are theoretically identical, so no code calling this should fail to work if this /// returns false. /// /// The first double to compare. /// The second double to compare. /// The result of the GreaterThan comparision. [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] public static bool GreaterThan( double value1, double value2 ) { return ( value1 > value2 ) && !AreClose( value1, value2 ); } /// /// LessThanOrClose returns whether or not the first double is less than or close to /// the second double. That is, whether or not the first is strictly less than or within /// epsilon of the other number. /// There are plenty of ways for this to return false even for numbers which /// are theoretically identical, so no code calling this should fail to work if this /// returns false. /// /// The first double to compare. /// The second double to compare. /// The result of the LessThanOrClose comparision. [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] public static bool LessThanOrClose( double value1, double value2 ) { return ( value1 < value2 ) || AreClose( value1, value2 ); } /// /// GreaterThanOrClose returns whether or not the first double is greater than or close to /// the second double. That is, whether or not the first is strictly greater than or within /// epsilon of the other number. /// There are plenty of ways for this to return false even for numbers which /// are theoretically identical, so no code calling this should fail to work if this /// returns false. /// /// The first double to compare. /// The second double to compare. /// The result of the GreaterThanOrClose comparision. [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] public static bool GreaterThanOrClose( double value1, double value2 ) { return ( value1 > value2 ) || AreClose( value1, value2 ); } /// /// Test to see if a double is a finite number (is not NaN or Infinity). /// /// The value to test. /// Whether or not the value is a finite number. [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] public static bool IsFinite( double value ) { return !double.IsNaN( value ) && !double.IsInfinity( value ); } /// /// Test to see if a double a valid size value (is finite and > 0). /// /// The value to test. /// Whether or not the value is a valid size value. [SuppressMessage( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )] public static bool IsValidSize( double value ) { return IsFinite( value ) && GreaterThanOrClose( value, 0 ); } } }