Browse Source

Fix machine epsilon for double

pull/4096/head
Rustam Sayfutdinov 6 years ago
parent
commit
006186b981
  1. 9
      src/Avalonia.Base/Utilities/MathUtilities.cs
  2. 51
      tests/Avalonia.Base.UnitTests/Utilities/MathUtilitiesTests.cs

9
src/Avalonia.Base/Utilities/MathUtilities.cs

@ -8,6 +8,9 @@ namespace Avalonia.Utilities
/// </summary>
public static class MathUtilities
{
// smallest such that 1.0+DoubleEpsilon != 1.0
private const double DoubleEpsilon = 2.2204460492503131e-016;
/// <summary>
/// AreClose - Returns whether or not two doubles are "close". That is, whether or
/// not they are within epsilon of each other.
@ -18,7 +21,7 @@ namespace Avalonia.Utilities
{
//in case they are Infinities (then epsilon check does not work)
if (value1 == value2) return true;
double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * double.Epsilon;
double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DoubleEpsilon;
double delta = value1 - value2;
return (-eps < delta) && (eps > delta);
}
@ -78,7 +81,7 @@ namespace Avalonia.Utilities
/// <param name="value"> The double to compare to 1. </param>
public static bool IsOne(double value)
{
return Math.Abs(value - 1.0) < 10.0 * double.Epsilon;
return Math.Abs(value - 1.0) < 10.0 * DoubleEpsilon;
}
/// <summary>
@ -88,7 +91,7 @@ namespace Avalonia.Utilities
/// <param name="value"> The double to compare to 0. </param>
public static bool IsZero(double value)
{
return Math.Abs(value) < 10.0 * double.Epsilon;
return Math.Abs(value) < 10.0 * DoubleEpsilon;
}
/// <summary>

51
tests/Avalonia.Base.UnitTests/Utilities/MathUtilitiesTests.cs

@ -0,0 +1,51 @@
using Avalonia.Utilities;
using Xunit;
namespace Avalonia.Base.UnitTests.Utilities
{
public class MathUtilitiesTests
{
[Fact]
public void Two_Equivalent_Double_Values_Are_Close()
{
const int N = 10;
var x = 42.42;
var y = 0.0;
var dx = x / N;
for (var i = 0; i < N; ++i)
y += dx;
var actual = MathUtilities.AreClose(x, y);
Assert.True(actual);
}
[Fact]
public void Calculated_Double_One_Is_One()
{
const int N = 10;
var dx = 1.0 / N;
var x = 0.0;
for (var i = 0; i < N; ++i)
x += dx;
var actual = MathUtilities.IsOne(x);
Assert.True(actual);
}
[Fact]
public void Calculated_Double_Zero_Is_Zero()
{
const int N = 10;
var x = 1.0;
var dx = x / N;
for (var i = 0; i < N; ++i)
x -= dx;
var actual = MathUtilities.IsZero(x);
Assert.True(actual);
}
}
}
Loading…
Cancel
Save