Browse Source

LA: simplify matrix equality

la-knuth
Christoph Ruegg 14 years ago
parent
commit
b413ac5b21
  1. 53
      src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs
  2. 72
      src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs
  3. 53
      src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs
  4. 72
      src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs
  5. 53
      src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs
  6. 72
      src/Numerics/LinearAlgebra/Double/SparseMatrix.cs
  7. 46
      src/Numerics/LinearAlgebra/Generic/Matrix.cs
  8. 53
      src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs
  9. 72
      src/Numerics/LinearAlgebra/Single/SparseMatrix.cs
  10. 59
      src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs
  11. 79
      src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs
  12. 73
      src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs

53
src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs

@ -189,59 +189,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new SparseVector(size);
}
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="obj">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="obj"/> parameter; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
var diagonalMatrix = obj as DiagonalMatrix;
if (diagonalMatrix == null)
{
return base.Equals(obj);
}
// Accept if the argument is the same object as this
if (ReferenceEquals(this, diagonalMatrix))
{
return true;
}
if (diagonalMatrix._data.Length != _data.Length)
{
return false;
}
// If all else fails, perform element wise comparison.
return !_data.Where((t, i) => t != diagonalMatrix._data[i]).Any();
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
var hashNum = Math.Min(_data.Length, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
hash = hash*31 + _data[i].GetHashCode();
}
}
return hash;
}
#region Elementary operations
/// <summary>

72
src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs

@ -588,27 +588,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return ret;
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
var values = _storage.Values;
var hashNum = Math.Min(_storage.ValueCount, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
hash = hash*31 + values[i].GetHashCode();
}
}
return hash;
}
/// <summary>
/// Returns the transpose of this matrix.
/// </summary>
@ -867,57 +846,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
#endregion
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="other"/> parameter; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(Matrix<Complex> other)
{
if (other == null)
{
return false;
}
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
{
return false;
}
// Accept if the argument is the same object as this.
if (ReferenceEquals(this, other))
{
return true;
}
var sparseMatrix = other as SparseMatrix;
if (sparseMatrix == null)
{
return base.Equals(other);
}
var otherStorage = sparseMatrix.Raw;
if (_storage.ValueCount != otherStorage.ValueCount)
{
return false;
}
// If all else fails, perform element wise comparison.
for (var index = 0; index < _storage.ValueCount; index++)
{
if (!_storage.Values[index].AlmostEqual(otherStorage.Values[index]) || _storage.ColumnIndices[index] != otherStorage.ColumnIndices[index])
{
return false;
}
}
return true;
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>

53
src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs

@ -189,59 +189,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new SparseVector(size);
}
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="obj">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="obj"/> parameter; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
var diagonalMatrix = obj as DiagonalMatrix;
if (diagonalMatrix == null)
{
return base.Equals(obj);
}
// Accept if the argument is the same object as this
if (ReferenceEquals(this, diagonalMatrix))
{
return true;
}
if (diagonalMatrix._data.Length != _data.Length)
{
return false;
}
// If all else fails, perform element wise comparison.
return !_data.Where((t, i) => t != diagonalMatrix._data[i]).Any();
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
var hashNum = Math.Min(_data.Length, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
hash = hash*31 + _data[i].GetHashCode();
}
}
return hash;
}
#region Elementary operations
/// <summary>

72
src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs

@ -588,27 +588,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return ret;
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
var values = _storage.Values;
var hashNum = Math.Min(_storage.ValueCount, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
hash = hash*31 + values[i].GetHashCode();
}
}
return hash;
}
/// <summary>
/// Returns the transpose of this matrix.
/// </summary>
@ -867,57 +846,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
#endregion
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="other"/> parameter; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(Matrix<Complex32> other)
{
if (other == null)
{
return false;
}
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
{
return false;
}
// Accept if the argument is the same object as this.
if (ReferenceEquals(this, other))
{
return true;
}
var sparseMatrix = other as SparseMatrix;
if (sparseMatrix == null)
{
return base.Equals(other);
}
var otherStorage = sparseMatrix.Raw;
if (_storage.ValueCount != otherStorage.ValueCount)
{
return false;
}
// If all else fails, perform element wise comparison.
for (var index = 0; index < _storage.ValueCount; index++)
{
if (!_storage.Values[index].AlmostEqual(otherStorage.Values[index]) || _storage.ColumnIndices[index] != otherStorage.ColumnIndices[index])
{
return false;
}
}
return true;
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>

53
src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs

@ -188,59 +188,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new SparseVector(size);
}
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="obj">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="obj"/> parameter; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
var diagonalMatrix = obj as DiagonalMatrix;
if (diagonalMatrix == null)
{
return base.Equals(obj);
}
// Accept if the argument is the same object as this
if (ReferenceEquals(this, diagonalMatrix))
{
return true;
}
if (diagonalMatrix._data.Length != _data.Length)
{
return false;
}
// If all else fails, perform element wise comparison.
return !_data.Where((t, i) => t != diagonalMatrix._data[i]).Any();
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
var hashNum = Math.Min(_data.Length, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
hash = hash*31 + _data[i].GetHashCode();
}
}
return hash;
}
#region Elementary operations
/// <summary>

72
src/Numerics/LinearAlgebra/Double/SparseMatrix.cs

@ -587,27 +587,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return ret;
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
var values = _storage.Values;
var hashNum = Math.Min(_storage.ValueCount, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
hash = hash*31 + values[i].GetHashCode();
}
}
return hash;
}
/// <summary>
/// Returns the transpose of this matrix.
/// </summary>
@ -865,57 +844,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
#endregion
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="other"/> parameter; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(Matrix<double> other)
{
if (other == null)
{
return false;
}
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
{
return false;
}
// Accept if the argument is the same object as this.
if (ReferenceEquals(this, other))
{
return true;
}
var sparseMatrix = other as SparseMatrix;
if (sparseMatrix == null)
{
return base.Equals(other);
}
var otherStorage = sparseMatrix.Raw;
if (_storage.ValueCount != otherStorage.ValueCount)
{
return false;
}
// If all else fails, perform element wise comparison.
for (var index = 0; index < _storage.ValueCount; index++)
{
if (!_storage.Values[index].AlmostEqual(otherStorage.Values[index]) || _storage.ColumnIndices[index] != otherStorage.ColumnIndices[index])
{
return false;
}
}
return true;
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>

46
src/Numerics/LinearAlgebra/Generic/Matrix.cs

@ -221,7 +221,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
public virtual Matrix<T> Clone()
{
var result = CreateMatrix(RowCount, ColumnCount);
CopyTo(result);
Storage.CopyTo(result.Storage);
return result;
}
@ -1331,38 +1331,14 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="other"/> parameter; otherwise, <c>false</c>.
/// </returns>
public virtual bool Equals(Matrix<T> other)
public bool Equals(Matrix<T> other)
{
// Reject equality when the argument is null or has a different shape.
if (other == null)
{
return false;
}
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
{
return false;
}
// Accept if the argument is the same object as this.
if (ReferenceEquals(this, other))
{
return true;
}
// If all else fails, perform element wise comparison.
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
if (!At(row, column).Equals(other.At(row, column)))
{
return false;
}
}
}
return true;
return Storage.Equals(other.Storage);
}
#endregion
@ -1419,7 +1395,8 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// </returns>
public override bool Equals(object obj)
{
return Equals(obj as Matrix<T>);
var other = obj as Matrix<T>;
return other != null && Storage.Equals(other.Storage);
}
/// <summary>
@ -1430,18 +1407,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// </returns>
public override int GetHashCode()
{
var hashNum = Math.Min(RowCount*ColumnCount, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
var col = i%ColumnCount;
var row = (i - col)/RowCount;
hash = hash*31 + At(row, col).GetHashCode();
}
}
return hash;
return Storage.GetHashCode();
}
#endregion

53
src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs

@ -188,59 +188,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new SparseVector(size);
}
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="obj">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="obj"/> parameter; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
var diagonalMatrix = obj as DiagonalMatrix;
if (diagonalMatrix == null)
{
return base.Equals(obj);
}
// Accept if the argument is the same object as this
if (ReferenceEquals(this, diagonalMatrix))
{
return true;
}
if (diagonalMatrix._data.Length != _data.Length)
{
return false;
}
// If all else fails, perform element wise comparison.
return !_data.Where((t, i) => t != diagonalMatrix._data[i]).Any();
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
var hashNum = Math.Min(_data.Length, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
hash = hash*31 + _data[i].GetHashCode();
}
}
return hash;
}
#region Elementary operations
/// <summary>

72
src/Numerics/LinearAlgebra/Single/SparseMatrix.cs

@ -586,27 +586,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return ret;
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
var values = _storage.Values;
var hashNum = Math.Min(_storage.ValueCount, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
hash = hash*31 + values[i].GetHashCode();
}
}
return hash;
}
/// <summary>
/// Returns the transpose of this matrix.
@ -865,57 +844,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
#endregion
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="other"/> parameter; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(Matrix<float> other)
{
if (other == null)
{
return false;
}
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
{
return false;
}
// Accept if the argument is the same object as this.
if (ReferenceEquals(this, other))
{
return true;
}
var sparseMatrix = other as SparseMatrix;
if (sparseMatrix == null)
{
return base.Equals(other);
}
var otherStorage = sparseMatrix.Raw;
if (_storage.ValueCount != otherStorage.ValueCount)
{
return false;
}
// If all else fails, perform element wise comparison.
for (var index = 0; index < _storage.ValueCount; index++)
{
if (!_storage.Values[index].AlmostEqual(otherStorage.Values[index]) || _storage.ColumnIndices[index] != otherStorage.ColumnIndices[index])
{
return false;
}
}
return true;
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>

59
src/Numerics/LinearAlgebra/Storage/DiagonalMatrixStorage.cs

@ -1,4 +1,5 @@
using System;
using System.Linq;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Storage
@ -63,6 +64,64 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
Array.Clear(Data, 0, Data.Length);
}
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="other"/> parameter; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(MatrixStorage<T> other)
{
var diagonal = other as DiagonalMatrixStorage<T>;
if (diagonal == null)
{
return base.Equals(other);
}
// Reject equality when the argument is null or has a different shape.
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
{
return false;
}
// Accept if the argument is the same object as this.
if (ReferenceEquals(this, other))
{
return true;
}
if (diagonal.Data.Length != Data.Length)
{
return false;
}
// If all else fails, perform element wise comparison.
return !Data.Where((t, i) => !t.Equals(diagonal.Data[i])).Any();
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
var hashNum = Math.Min(Data.Length, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
hash = hash * 31 + Data[i].GetHashCode();
}
}
return hash;
}
/// <remarks>Parameters assumed to be validated already.</remarks>
public override void CopyTo(MatrixStorage<T> target, bool skipClearing = false)
{

79
src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs

@ -3,7 +3,8 @@ using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Storage
{
public abstract partial class MatrixStorage<T> where T : struct, IEquatable<T>, IFormattable
public abstract partial class MatrixStorage<T> : IEquatable<MatrixStorage<T>>
where T : struct, IEquatable<T>, IFormattable
{
// [ruegg] public fields are OK here
@ -106,6 +107,82 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
}
}
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="other"/> parameter; otherwise, <c>false</c>.
/// </returns>
public virtual bool Equals(MatrixStorage<T> other)
{
// Reject equality when the argument is null or has a different shape.
if (other == null)
{
return false;
}
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
{
return false;
}
// Accept if the argument is the same object as this.
if (ReferenceEquals(this, other))
{
return true;
}
// If all else fails, perform element wise comparison.
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
if (!At(row, column).Equals(other.At(row, column)))
{
return false;
}
}
}
return true;
}
/// <summary>
/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
/// </summary>
/// <returns>
/// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
/// </returns>
/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param><filterpriority>2</filterpriority>
public override sealed bool Equals(object obj)
{
return Equals(obj as MatrixStorage<T>);
}
/// <summary>
/// Serves as a hash function for a particular type.
/// </summary>
/// <returns>
/// A hash code for the current <see cref="T:System.Object"/>.
/// </returns>
public override int GetHashCode()
{
var hashNum = Math.Min(RowCount*ColumnCount, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
var col = i%ColumnCount;
var row = (i - col)/RowCount;
hash = hash*31 + At(row, col).GetHashCode();
}
}
return hash;
}
/// <remarks>Parameters assumed to be validated already.</remarks>
public virtual void CopyTo(MatrixStorage<T> target, bool skipClearing = false)
{

73
src/Numerics/LinearAlgebra/Storage/SparseCompressedRowMatrixStorage.cs

@ -217,6 +217,79 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
return delta;
}
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">
/// An object to compare with this object.
/// </param>
/// <returns>
/// <c>true</c> if the current object is equal to the <paramref name="other"/> parameter; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(MatrixStorage<T> other)
{
// Reject equality when the argument is null or has a different shape.
if (other == null)
{
return false;
}
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
{
return false;
}
// Accept if the argument is the same object as this.
if (ReferenceEquals(this, other))
{
return true;
}
var sparse = other as SparseCompressedRowMatrixStorage<T>;
if (sparse == null)
{
return base.Equals(other);
}
if (ValueCount != sparse.ValueCount)
{
// TODO: this is not always correct
return false;
}
// If all else fails, perform element wise comparison.
for (var index = 0; index < ValueCount; index++)
{
// TODO: AlmostEquals
if (!Values[index].Equals(sparse.Values[index]) || ColumnIndices[index] != sparse.ColumnIndices[index])
{
return false;
}
}
return true;
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
var values = Values;
var hashNum = Math.Min(ValueCount, 25);
int hash = 17;
unchecked
{
for (var i = 0; i < hashNum; i++)
{
hash = hash * 31 + values[i].GetHashCode();
}
}
return hash;
}
/// <remarks>Parameters assumed to be validated already.</remarks>
public override void CopyTo(MatrixStorage<T> target, bool skipClearing = false)
{

Loading…
Cancel
Save