Skip to content

Commit

Permalink
Fixed a rounding bug in the Matrix GetHashCode that would cause matri…
Browse files Browse the repository at this point in the history
…ces that were deemed equal to not have the same hash code
  • Loading branch information
moserware committed Apr 26, 2010
1 parent 592a82b commit 9bc97fa
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 6 deletions.
16 changes: 10 additions & 6 deletions Skills/Numerics/Matrix.cs
Expand Up @@ -9,6 +9,10 @@ namespace Moserware.Numerics
/// </summary>
internal class Matrix
{
// Anything smaller than this will be assumed to be rounding error in terms of equality matching
private const int FractionalDigitsToRoundTo = 10;
private static readonly double ErrorTolerance = Math.Pow(0.1, FractionalDigitsToRoundTo); // e.g. 1/10^10

protected double[][] _MatrixRowValues;
// Note: some properties like Determinant, Inverse, etc are properties instead
// of methods to make the syntax look nicer even though this sort of goes against
Expand Down Expand Up @@ -386,9 +390,7 @@ private double GetCofactor(int rowToRemove, int columnToRemove)
{
return false;
}

const double errorTolerance = 0.0000000000001;


for (int currentRow = 0; currentRow < a.Rows; currentRow++)
{
for (int currentColumn = 0; currentColumn < a.Columns; currentColumn++)
Expand All @@ -397,7 +399,7 @@ private double GetCofactor(int rowToRemove, int columnToRemove)
Math.Abs(a._MatrixRowValues[currentRow][currentColumn] -
b._MatrixRowValues[currentRow][currentColumn]);

if (delta > errorTolerance)
if (delta > ErrorTolerance)
{
return false;
}
Expand Down Expand Up @@ -426,7 +428,9 @@ public override int GetHashCode()

for (int currentColumn = 0; currentColumn < Columns; currentColumn++)
{
result += multiplier*_MatrixRowValues[currentRow][currentColumn];
double cellValue = _MatrixRowValues[currentRow][currentColumn];
double roundedValue = Math.Round(cellValue, FractionalDigitsToRoundTo);
result += multiplier*roundedValue;
}
}
}
Expand All @@ -443,7 +447,7 @@ public override int GetHashCode()
int hashCode = BitConverter.ToInt32(finalBytes, 0);
return hashCode;
}

public override bool Equals(object obj)
{
var other = obj as Matrix;
Expand Down
Binary file modified Skills/bin/Debug/Moserware.Skills.dll
Binary file not shown.
Binary file modified Skills/bin/Debug/Moserware.Skills.pdb
Binary file not shown.
Binary file modified Skills/bin/Release/Moserware.Skills.dll
Binary file not shown.
Binary file modified Skills/bin/Release/Moserware.Skills.pdb
Binary file not shown.
10 changes: 10 additions & 0 deletions UnitTests/Numerics/MatrixTests.cs
Expand Up @@ -121,6 +121,16 @@ public void EqualsTest()
Assert.AreEqual(d, f);
Assert.AreEqual(d.GetHashCode(), f.GetHashCode());

// Test rounding (thanks to nsp on GitHub for finding this case)
var g = new SquareMatrix(1, 2.00000000000001,
3, 4);

var h = new SquareMatrix(1, 2,
3, 4);

Assert.IsTrue(g == h);
Assert.AreEqual(g, h);
Assert.AreEqual(g.GetHashCode(), h.GetHashCode());
}

[Test]
Expand Down

0 comments on commit 9bc97fa

Please sign in to comment.