From 59b1005d7f5fb6bfa0e5c2bd8a8befb3b80c2eb5 Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sun, 20 Oct 2013 03:14:01 +0200 Subject: [PATCH] LA/Precision: Matrix norms double-valued (like vectors); generic AlmostEqual support --- .../LinearAlgebra/Factorization/Svd.cs | 2 +- .../LinearAlgebra/Complex/DenseMatrix.cs | 20 +-- .../LinearAlgebra/Complex/DiagonalMatrix.cs | 21 ++- .../Complex/Factorization/Svd.cs | 2 +- src/Numerics/LinearAlgebra/Complex/Matrix.cs | 60 ++++---- .../LinearAlgebra/Complex/SparseMatrix.cs | 52 +++---- .../LinearAlgebra/Complex32/DenseMatrix.cs | 20 +-- .../LinearAlgebra/Complex32/DiagonalMatrix.cs | 21 ++- .../Complex32/Factorization/Svd.cs | 2 +- .../LinearAlgebra/Complex32/Matrix.cs | 61 ++++---- .../LinearAlgebra/Complex32/SparseMatrix.cs | 56 ++++--- .../LinearAlgebra/Double/DenseMatrix.cs | 14 +- .../LinearAlgebra/Double/DiagonalMatrix.cs | 15 +- .../LinearAlgebra/Double/Factorization/Svd.cs | 2 +- src/Numerics/LinearAlgebra/Double/Matrix.cs | 56 +++---- .../LinearAlgebra/Double/SparseMatrix.cs | 53 +++---- .../LinearAlgebra/Factorization/Svd.cs | 2 +- .../LinearAlgebra/Matrix.Arithmetic.cs | 21 +++ src/Numerics/LinearAlgebra/Matrix.cs | 21 --- .../LinearAlgebra/Single/DenseMatrix.cs | 18 +-- .../LinearAlgebra/Single/DiagonalMatrix.cs | 21 ++- .../LinearAlgebra/Single/Factorization/Svd.cs | 2 +- src/Numerics/LinearAlgebra/Single/Matrix.cs | 60 ++++---- .../LinearAlgebra/Single/SparseMatrix.cs | 57 ++++---- src/Numerics/Precision.Equality.cs | 138 +++++++++--------- .../Complex32/MatrixTests.cs | 25 ++-- 26 files changed, 384 insertions(+), 438 deletions(-) diff --git a/src/Examples/LinearAlgebra/Factorization/Svd.cs b/src/Examples/LinearAlgebra/Factorization/Svd.cs index bb856732..7bc52acf 100644 --- a/src/Examples/LinearAlgebra/Factorization/Svd.cs +++ b/src/Examples/LinearAlgebra/Factorization/Svd.cs @@ -135,7 +135,7 @@ namespace Examples.LinearAlgebra.FactorizationExamples // 10. 2-norm of the matrix Console.WriteLine(@"10. 2-norm of the matrix"); - Console.WriteLine(svd.Norm2); + Console.WriteLine(svd.L2Norm); Console.WriteLine(); // 11. Rank of the matrix diff --git a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs index 6a979bdf..635eb9cf 100644 --- a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs @@ -428,23 +428,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex /// Calculates the L1 norm. /// The L1 norm of the matrix. - public override Complex L1Norm() + public override double L1Norm() { - return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _values); + return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _values).Real; } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override Complex FrobeniusNorm() + /// Calculates the infinity norm of this matrix. + /// The infinity norm of this matrix. + public override double InfinityNorm() { - return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values); + return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _values).Real; } - /// Calculates the infinity norm of this matrix. - /// The infinity norm of this matrix. - public override Complex InfinityNorm() + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() { - return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _values); + return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values).Real; } /// diff --git a/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs index c84083b5..29ee2201 100644 --- a/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs @@ -654,33 +654,32 @@ namespace MathNet.Numerics.LinearAlgebra.Complex /// Calculates the L1 norm. /// The L1 norm of the matrix. - public override Complex L1Norm() + public override double L1Norm() { return _data.Aggregate(double.NegativeInfinity, (current, t) => Math.Max(current, t.Magnitude)); } /// Calculates the L2 norm. /// The L2 norm of the matrix. - public override Complex L2Norm() + public override double L2Norm() { return _data.Aggregate(double.NegativeInfinity, (current, t) => Math.Max(current, t.Magnitude)); } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override Complex FrobeniusNorm() - { - var norm = _data.Sum(t => t.Magnitude * t.Magnitude); - return Math.Sqrt(norm); - } - /// Calculates the infinity norm of this matrix. /// The infinity norm of this matrix. - public override Complex InfinityNorm() + public override double InfinityNorm() { return L1Norm(); } + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() + { + return Math.Sqrt(_data.Sum(t => t.Magnitude * t.Magnitude)); + } + /// Calculates the condition number of this matrix. /// The condition number of the matrix. public override Complex ConditionNumber() diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/Svd.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/Svd.cs index 69166e4b..61f5d5e7 100644 --- a/src/Numerics/LinearAlgebra/Complex/Factorization/Svd.cs +++ b/src/Numerics/LinearAlgebra/Complex/Factorization/Svd.cs @@ -79,7 +79,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization /// Gets the two norm of the . /// /// The 2-norm of the . - public override Complex Norm2 + public override double L2Norm { get { diff --git a/src/Numerics/LinearAlgebra/Complex/Matrix.cs b/src/Numerics/LinearAlgebra/Complex/Matrix.cs index cd29db07..afebdc5f 100644 --- a/src/Numerics/LinearAlgebra/Complex/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/Matrix.cs @@ -59,76 +59,68 @@ namespace MathNet.Numerics.LinearAlgebra.Complex /// Calculates the L1 norm. /// The L1 norm of the matrix. - public override Complex L1Norm() + public override double L1Norm() { - var norm = 0.0; + var norm = 0d; for (var j = 0; j < ColumnCount; j++) { - var s = 0.0; + var s = 0d; for (var i = 0; i < RowCount; i++) { s += At(i, j).Magnitude; } - norm = Math.Max(norm, s); } - return norm; } - /// - /// Returns the conjugate transpose of this matrix. - /// - /// The conjugate transpose of this matrix. - public override Matrix ConjugateTranspose() + /// Calculates the infinity norm of this matrix. + /// The infinity norm of this matrix. + public override double InfinityNorm() { - var ret = CreateMatrix(ColumnCount, RowCount); - for (var j = 0; j < ColumnCount; j++) + var norm = 0d; + for (var i = 0; i < RowCount; i++) { - for (var i = 0; i < RowCount; i++) + var s = 0d; + for (var j = 0; j < ColumnCount; j++) { - ret.At(j, i, At(i, j).Conjugate()); + s += At(i, j).Magnitude; } + norm = Math.Max(norm, s); } - - return ret; + return norm; } /// Calculates the Frobenius norm of this matrix. /// The Frobenius norm of this matrix. - public override Complex FrobeniusNorm() + public override double FrobeniusNorm() { var transpose = ConjugateTranspose(); var aat = this * transpose; - - var norm = 0.0; + var norm = 0d; for (var i = 0; i < RowCount; i++) { norm += aat.At(i, i).Magnitude; } - - norm = Math.Sqrt(norm); - - return norm; + return Math.Sqrt(norm); } - /// Calculates the infinity norm of this matrix. - /// The infinity norm of this matrix. - public override Complex InfinityNorm() + /// + /// Returns the conjugate transpose of this matrix. + /// + /// The conjugate transpose of this matrix. + public override Matrix ConjugateTranspose() { - var norm = 0.0; - for (var i = 0; i < RowCount; i++) + var ret = CreateMatrix(ColumnCount, RowCount); + for (var j = 0; j < ColumnCount; j++) { - var s = 0.0; - for (var j = 0; j < ColumnCount; j++) + for (var i = 0; i < RowCount; i++) { - s += At(i, j).Magnitude; + ret.At(j, i, At(i, j).Conjugate()); } - - norm = Math.Max(norm, s); } - return norm; + return ret; } /// diff --git a/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs index 0565d1a9..b2c2d1dc 100644 --- a/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs @@ -674,64 +674,58 @@ namespace MathNet.Numerics.LinearAlgebra.Complex return new SparseMatrix(ret); } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override Complex FrobeniusNorm() + /// Calculates the infinity norm of this matrix. + /// The infinity norm of this matrix. + public override double InfinityNorm() { - var aat = (SparseCompressedRowMatrixStorage) (this*ConjugateTranspose()).Storage; + var rowPointers = _storage.RowPointers; + var values = _storage.Values; var norm = 0d; - - for (var i = 0; i < aat.RowCount; i++) + for (var i = 0; i < RowCount; i++) { - var startIndex = aat.RowPointers[i]; - var endIndex = aat.RowPointers[i + 1]; + var startIndex = rowPointers[i]; + var endIndex = rowPointers[i + 1]; if (startIndex == endIndex) { continue; } + var s = 0d; for (var j = startIndex; j < endIndex; j++) { - if (i == aat.ColumnIndices[j]) - { - norm += aat.Values[j].Magnitude; - } + s += values[j].Magnitude; } + norm = Math.Max(norm, s); } - - norm = Math.Sqrt(norm); return norm; } - /// Calculates the infinity norm of this matrix. - /// The infinity norm of this matrix. - public override Complex InfinityNorm() + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() { - var rowPointers = _storage.RowPointers; - var values = _storage.Values; - + var aat = (SparseCompressedRowMatrixStorage) (this*ConjugateTranspose()).Storage; var norm = 0d; - for (var i = 0; i < RowCount; i++) + for (var i = 0; i < aat.RowCount; i++) { - var startIndex = rowPointers[i]; - var endIndex = rowPointers[i + 1]; + var startIndex = aat.RowPointers[i]; + var endIndex = aat.RowPointers[i + 1]; if (startIndex == endIndex) { continue; } - var s = 0.0; for (var j = startIndex; j < endIndex; j++) { - s += values[j].Magnitude; + if (i == aat.ColumnIndices[j]) + { + norm += aat.Values[j].Magnitude; + } } - - norm = Math.Max(norm, s); } - - return norm; + return Math.Sqrt(norm); } /// diff --git a/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs index 13b93d3b..021eae2c 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs @@ -423,23 +423,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 /// Calculates the L1 norm. /// The L1 norm of the matrix. - public override Complex32 L1Norm() + public override double L1Norm() { - return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _values); + return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _values).Real; } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override Complex32 FrobeniusNorm() + /// Calculates the infinity norm of this matrix. + /// The infinity norm of this matrix. + public override double InfinityNorm() { - return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values); + return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _values).Real; } - /// Calculates the infinity norm of this matrix. - /// The infinity norm of this matrix. - public override Complex32 InfinityNorm() + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() { - return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _values); + return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values).Real; } /// diff --git a/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs index 183044ba..d1bde21a 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs @@ -649,33 +649,32 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 /// Calculates the L1 norm. /// The L1 norm of the matrix. - public override Complex32 L1Norm() + public override double L1Norm() { return _data.Aggregate(float.NegativeInfinity, (current, t) => Math.Max(current, t.Magnitude)); } /// Calculates the L2 norm. /// The L2 norm of the matrix. - public override Complex32 L2Norm() + public override double L2Norm() { return _data.Aggregate(float.NegativeInfinity, (current, t) => Math.Max(current, t.Magnitude)); } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override Complex32 FrobeniusNorm() - { - var norm = _data.Sum(t => t.Magnitude * t.Magnitude); - return Convert.ToSingle(Math.Sqrt(norm)); - } - /// Calculates the infinity norm of this matrix. /// The infinity norm of this matrix. - public override Complex32 InfinityNorm() + public override double InfinityNorm() { return L1Norm(); } + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() + { + return Math.Sqrt(_data.Sum(t => t.Magnitude * t.Magnitude)); + } + /// Calculates the condition number of this matrix. /// The condition number of the matrix. public override Complex32 ConditionNumber() diff --git a/src/Numerics/LinearAlgebra/Complex32/Factorization/Svd.cs b/src/Numerics/LinearAlgebra/Complex32/Factorization/Svd.cs index ca464f15..c4b17da7 100644 --- a/src/Numerics/LinearAlgebra/Complex32/Factorization/Svd.cs +++ b/src/Numerics/LinearAlgebra/Complex32/Factorization/Svd.cs @@ -74,7 +74,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization /// Gets the two norm of the . /// /// The 2-norm of the . - public override Complex32 Norm2 + public override double L2Norm { get { diff --git a/src/Numerics/LinearAlgebra/Complex32/Matrix.cs b/src/Numerics/LinearAlgebra/Complex32/Matrix.cs index 1dd2ab2b..2ab02f16 100644 --- a/src/Numerics/LinearAlgebra/Complex32/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/Matrix.cs @@ -54,76 +54,67 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 /// Calculates the L1 norm. /// The L1 norm of the matrix. - public override Complex32 L1Norm() + public override double L1Norm() { - var norm = 0.0f; + var norm = 0d; for (var j = 0; j < ColumnCount; j++) { - var s = 0.0f; + var s = 0d; for (var i = 0; i < RowCount; i++) { s += At(i, j).Magnitude; } - norm = Math.Max(norm, s); } - return norm; } - /// - /// Returns the conjugate transpose of this matrix. - /// - /// The conjugate transpose of this matrix. - public override Matrix ConjugateTranspose() + /// Calculates the infinity norm of this matrix. + /// The infinity norm of this matrix. + public override double InfinityNorm() { - var ret = CreateMatrix(ColumnCount, RowCount); - for (var j = 0; j < ColumnCount; j++) + var norm = 0d; + for (var i = 0; i < RowCount; i++) { - for (var i = 0; i < RowCount; i++) + var s = 0d; + for (var j = 0; j < ColumnCount; j++) { - ret.At(j, i, At(i, j).Conjugate()); + s += At(i, j).Magnitude; } + norm = Math.Max(norm, s); } - - return ret; + return norm; } /// Calculates the Frobenius norm of this matrix. /// The Frobenius norm of this matrix. - public override Complex32 FrobeniusNorm() + public override double FrobeniusNorm() { var transpose = ConjugateTranspose(); var aat = this * transpose; - - var norm = 0.0f; + var norm = 0d; for (var i = 0; i < RowCount; i++) { norm += aat.At(i, i).Magnitude; } - - norm = Convert.ToSingle(Math.Sqrt(norm)); - - return norm; + return Math.Sqrt(norm); } - /// Calculates the infinity norm of this matrix. - /// The infinity norm of this matrix. - public override Complex32 InfinityNorm() + /// + /// Returns the conjugate transpose of this matrix. + /// + /// The conjugate transpose of this matrix. + public override Matrix ConjugateTranspose() { - var norm = 0.0f; - for (var i = 0; i < RowCount; i++) + var ret = CreateMatrix(ColumnCount, RowCount); + for (var j = 0; j < ColumnCount; j++) { - var s = 0.0f; - for (var j = 0; j < ColumnCount; j++) + for (var i = 0; i < RowCount; i++) { - s += At(i, j).Magnitude; + ret.At(j, i, At(i, j).Conjugate()); } - - norm = Math.Max(norm, s); } - - return norm; + return ret; } /// diff --git a/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs index 237a18d6..84a2e9fb 100644 --- a/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs @@ -669,64 +669,58 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 return new SparseMatrix(ret); } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override Complex32 FrobeniusNorm() + /// Calculates the infinity norm of this matrix. + /// The infinity norm of this matrix. + public override double InfinityNorm() { - var aat = (SparseCompressedRowMatrixStorage) (this*ConjugateTranspose()).Storage; - var norm = 0f; - - for (var i = 0; i < aat.RowCount; i++) + var rowPointers = _storage.RowPointers; + var values = _storage.Values; + var norm = 0d; + for (var i = 0; i < RowCount; i++) { - var startIndex = aat.RowPointers[i]; - var endIndex = aat.RowPointers[i + 1]; + var startIndex = rowPointers[i]; + var endIndex = rowPointers[i + 1]; if (startIndex == endIndex) { continue; } + var s = 0d; for (var j = startIndex; j < endIndex; j++) { - if (i == aat.ColumnIndices[j]) - { - norm += aat.Values[j].Magnitude; - } + s += values[j].Magnitude; } + norm = Math.Max(norm, s); } - - norm = Convert.ToSingle(Math.Sqrt(norm)); return norm; } - /// Calculates the infinity norm of this matrix. - /// The infinity norm of this matrix. - public override Complex32 InfinityNorm() + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() { - var rowPointers = _storage.RowPointers; - var values = _storage.Values; - - var norm = 0f; - for (var i = 0; i < RowCount; i++) + var aat = (SparseCompressedRowMatrixStorage) (this*ConjugateTranspose()).Storage; + var norm = 0d; + for (var i = 0; i < aat.RowCount; i++) { - var startIndex = rowPointers[i]; - var endIndex = rowPointers[i + 1]; + var startIndex = aat.RowPointers[i]; + var endIndex = aat.RowPointers[i + 1]; if (startIndex == endIndex) { continue; } - var s = 0.0f; for (var j = startIndex; j < endIndex; j++) { - s += values[j].Magnitude; + if (i == aat.ColumnIndices[j]) + { + norm += aat.Values[j].Magnitude; + } } - - norm = Math.Max(norm, s); } - - return norm; + return Math.Sqrt(norm); } /// diff --git a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs index 3e467e52..c7169274 100644 --- a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs @@ -425,13 +425,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _values); } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override double FrobeniusNorm() - { - return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values); - } - /// Calculates the infinity norm of this matrix. /// The infinity norm of this matrix. public override double InfinityNorm() @@ -439,6 +432,13 @@ namespace MathNet.Numerics.LinearAlgebra.Double return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _values); } + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() + { + return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values); + } + /// /// Add a scalar to each element of the matrix and stores the result in the result vector. /// diff --git a/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs index bfa292e1..cbad50e0 100644 --- a/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs @@ -655,14 +655,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double return _data.Aggregate(double.NegativeInfinity, (current, t) => Math.Max(current, Math.Abs(t))); } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override double FrobeniusNorm() - { - var norm = _data.Sum(t => t * t); - return Math.Sqrt(norm); - } - /// Calculates the infinity norm of this matrix. /// The infinity norm of this matrix. public override double InfinityNorm() @@ -670,6 +662,13 @@ namespace MathNet.Numerics.LinearAlgebra.Double return L1Norm(); } + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() + { + return Math.Sqrt(_data.Sum(t => t * t)); + } + /// Calculates the condition number of this matrix. /// The condition number of the matrix. public override double ConditionNumber() diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/Svd.cs b/src/Numerics/LinearAlgebra/Double/Factorization/Svd.cs index 5fe9c847..21622502 100644 --- a/src/Numerics/LinearAlgebra/Double/Factorization/Svd.cs +++ b/src/Numerics/LinearAlgebra/Double/Factorization/Svd.cs @@ -72,7 +72,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization /// Gets the two norm of the . /// /// The 2-norm of the . - public override double Norm2 + public override double L2Norm { get { diff --git a/src/Numerics/LinearAlgebra/Double/Matrix.cs b/src/Numerics/LinearAlgebra/Double/Matrix.cs index 210b8ada..bc4fa558 100644 --- a/src/Numerics/LinearAlgebra/Double/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Double/Matrix.cs @@ -54,28 +54,34 @@ namespace MathNet.Numerics.LinearAlgebra.Double /// The L1 norm of the matrix. public override double L1Norm() { - var norm = 0.0; + var norm = 0d; for (var j = 0; j < ColumnCount; j++) { - var s = 0.0; + var s = 0d; for (var i = 0; i < RowCount; i++) { s += Math.Abs(At(i, j)); } - norm = Math.Max(norm, s); } - return norm; } - /// - /// Returns the conjugate transpose of this matrix. - /// - /// The conjugate transpose of this matrix. - public override sealed Matrix ConjugateTranspose() + /// Calculates the infinity norm of this matrix. + /// The infinity norm of this matrix. + public override double InfinityNorm() { - return Transpose(); + var norm = 0d; + for (var i = 0; i < RowCount; i++) + { + var s = 0d; + for (var j = 0; j < ColumnCount; j++) + { + s += Math.Abs(At(i, j)); + } + norm = Math.Max(norm, s); + } + return norm; } /// Calculates the Frobenius norm of this matrix. @@ -84,35 +90,21 @@ namespace MathNet.Numerics.LinearAlgebra.Double { var transpose = Transpose(); var aat = this * transpose; - - var norm = 0.0; + var norm = 0d; for (var i = 0; i < RowCount; i++) { norm += aat.At(i, i); } - - norm = Math.Sqrt(norm); - - return norm; + return Math.Sqrt(norm); } - /// Calculates the infinity norm of this matrix. - /// The infinity norm of this matrix. - public override double InfinityNorm() + /// + /// Returns the conjugate transpose of this matrix. + /// + /// The conjugate transpose of this matrix. + public override sealed Matrix ConjugateTranspose() { - var norm = 0.0; - for (var i = 0; i < RowCount; i++) - { - var s = 0.0; - for (var j = 0; j < ColumnCount; j++) - { - s += Math.Abs(At(i, j)); - } - - norm = Math.Max(norm, s); - } - - return norm; + return Transpose(); } /// diff --git a/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs index a6540178..e67972fa 100644 --- a/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/SparseMatrix.cs @@ -668,17 +668,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double return new SparseMatrix(ret); } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override double FrobeniusNorm() + /// Calculates the infinity norm of this matrix. + /// The infinity norm of this matrix. + public override double InfinityNorm() { - var aat = (SparseCompressedRowMatrixStorage) (this*Transpose()).Storage; + var rowPointers = _storage.RowPointers; + var values = _storage.Values; var norm = 0d; - - for (var i = 0; i < aat.RowCount; i++) + for (var i = 0; i < RowCount; i++) { - var startIndex = aat.RowPointers[i]; - var endIndex = aat.RowPointers[i + 1]; + var startIndex = rowPointers[i]; + var endIndex = rowPointers[i + 1]; if (startIndex == endIndex) { @@ -686,30 +686,26 @@ namespace MathNet.Numerics.LinearAlgebra.Double continue; } + var s = 0d; for (var j = startIndex; j < endIndex; j++) { - if (i == aat.ColumnIndices[j]) - { - norm += Math.Abs(aat.Values[j]); - } + s += Math.Abs(values[j]); } + norm = Math.Max(norm, s); } - - return Math.Sqrt(norm); + return norm; } - /// Calculates the infinity norm of this matrix. - /// The infinity norm of this matrix. - public override double InfinityNorm() + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() { - var rowPointers = _storage.RowPointers; - var values = _storage.Values; - + var aat = (SparseCompressedRowMatrixStorage) (this*Transpose()).Storage; var norm = 0d; - for (var i = 0; i < RowCount; i++) + for (var i = 0; i < aat.RowCount; i++) { - var startIndex = rowPointers[i]; - var endIndex = rowPointers[i + 1]; + var startIndex = aat.RowPointers[i]; + var endIndex = aat.RowPointers[i + 1]; if (startIndex == endIndex) { @@ -717,16 +713,15 @@ namespace MathNet.Numerics.LinearAlgebra.Double continue; } - var s = 0d; for (var j = startIndex; j < endIndex; j++) { - s += Math.Abs(values[j]); + if (i == aat.ColumnIndices[j]) + { + norm += Math.Abs(aat.Values[j]); + } } - - norm = Math.Max(norm, s); } - - return norm; + return Math.Sqrt(norm); } /// diff --git a/src/Numerics/LinearAlgebra/Factorization/Svd.cs b/src/Numerics/LinearAlgebra/Factorization/Svd.cs index 227c0b36..0e3dc2f7 100644 --- a/src/Numerics/LinearAlgebra/Factorization/Svd.cs +++ b/src/Numerics/LinearAlgebra/Factorization/Svd.cs @@ -120,7 +120,7 @@ namespace MathNet.Numerics.LinearAlgebra.Factorization /// Gets the two norm of the . /// /// The 2-norm of the . - public abstract T Norm2 { get; } + public abstract double L2Norm { get; } /// /// Gets the condition number max(S) / min(S) diff --git a/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs b/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs index ffb839cd..54ef95d5 100644 --- a/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs +++ b/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs @@ -1148,6 +1148,27 @@ namespace MathNet.Numerics.LinearAlgebra return ret; } + /// Calculates the L1 norm. + /// The L1 norm of the matrix. + public abstract double L1Norm(); + + /// Calculates the L2 norm. + /// The L2 norm of the matrix. + /// For sparse matrices, the L2 norm is computed using a dense implementation of singular value decomposition. + /// In a later release, it will be replaced with a sparse implementation. + public virtual double L2Norm() + { + return Svd(false).L2Norm; + } + + /// Calculates the infinity norm of this matrix. + /// The infinity norm of this matrix. + public abstract double InfinityNorm(); + + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public abstract double FrobeniusNorm(); + #region Exceptions - possibly move elsewhere? internal static Exception DimensionsDontMatch(Matrix left, Matrix right, Matrix result, string paramName = null) diff --git a/src/Numerics/LinearAlgebra/Matrix.cs b/src/Numerics/LinearAlgebra/Matrix.cs index 9d167aa7..118f6302 100644 --- a/src/Numerics/LinearAlgebra/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Matrix.cs @@ -1251,27 +1251,6 @@ namespace MathNet.Numerics.LinearAlgebra lower.Storage.CopySubMatrixToUnchecked(result.Storage, 0, RowCount, lower.RowCount, 0, ColumnCount, lower.ColumnCount); } - /// Calculates the L1 norm. - /// The L1 norm of the matrix. - public abstract T L1Norm(); - - /// Calculates the L2 norm. - /// The L2 norm of the matrix. - /// For sparse matrices, the L2 norm is computed using a dense implementation of singular value decomposition. - /// In a later release, it will be replaced with a sparse implementation. - public virtual T L2Norm() - { - return Svd(false).Norm2; - } - - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public abstract T FrobeniusNorm(); - - /// Calculates the infinity norm of this matrix. - /// The infinity norm of this matrix. - public abstract T InfinityNorm(); - /// /// Gets a value indicating whether this matrix is symmetric. /// diff --git a/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs index 243c3a73..ce6407c1 100644 --- a/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs @@ -420,25 +420,25 @@ namespace MathNet.Numerics.LinearAlgebra.Single /// Calculates the L1 norm. /// The L1 norm of the matrix. - public override float L1Norm() + public override double L1Norm() { return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _values); } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override float FrobeniusNorm() - { - return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values); - } - /// Calculates the infinity norm of this matrix. /// The infinity norm of this matrix. - public override float InfinityNorm() + public override double InfinityNorm() { return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _values); } + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() + { + return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values); + } + /// /// Add a scalar to each element of the matrix and stores the result in the result vector. /// diff --git a/src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs b/src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs index 17db9841..41b87d71 100644 --- a/src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs +++ b/src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs @@ -643,33 +643,32 @@ namespace MathNet.Numerics.LinearAlgebra.Single /// Calculates the L1 norm. /// The L1 norm of the matrix. - public override float L1Norm() + public override double L1Norm() { return _data.Aggregate(float.NegativeInfinity, (current, t) => Math.Max(current, Math.Abs(t))); } /// Calculates the L2 norm. /// The L2 norm of the matrix. - public override float L2Norm() + public override double L2Norm() { return _data.Aggregate(float.NegativeInfinity, (current, t) => Math.Max(current, Math.Abs(t))); } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override float FrobeniusNorm() - { - var norm = _data.Sum(t => t * t); - return Convert.ToSingle(Math.Sqrt(norm)); - } - /// Calculates the infinity norm of this matrix. /// The infinity norm of this matrix. - public override float InfinityNorm() + public override double InfinityNorm() { return L1Norm(); } + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() + { + return Math.Sqrt(_data.Sum(t => t * t)); + } + /// Calculates the condition number of this matrix. /// The condition number of the matrix. public override float ConditionNumber() diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/Svd.cs b/src/Numerics/LinearAlgebra/Single/Factorization/Svd.cs index bc760b15..dfda2d7b 100644 --- a/src/Numerics/LinearAlgebra/Single/Factorization/Svd.cs +++ b/src/Numerics/LinearAlgebra/Single/Factorization/Svd.cs @@ -72,7 +72,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization /// Gets the two norm of the . /// /// The 2-norm of the . - public override float Norm2 + public override double L2Norm { get { diff --git a/src/Numerics/LinearAlgebra/Single/Matrix.cs b/src/Numerics/LinearAlgebra/Single/Matrix.cs index 2b081a82..902b86ff 100644 --- a/src/Numerics/LinearAlgebra/Single/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Single/Matrix.cs @@ -52,67 +52,59 @@ namespace MathNet.Numerics.LinearAlgebra.Single /// Calculates the L1 norm. /// The L1 norm of the matrix. - public override float L1Norm() + public override double L1Norm() { - var norm = 0.0f; + var norm = 0d; for (var j = 0; j < ColumnCount; j++) { - var s = 0.0f; + var s = 0d; for (var i = 0; i < RowCount; i++) { s += Math.Abs(At(i, j)); } - norm = Math.Max(norm, s); } - return norm; } - /// - /// Returns the conjugate transpose of this matrix. - /// - /// The conjugate transpose of this matrix. - public override sealed Matrix ConjugateTranspose() + /// Calculates the infinity norm of this matrix. + /// The infinity norm of this matrix. + public override double InfinityNorm() { - return Transpose(); + var norm = 0d; + for (var i = 0; i < RowCount; i++) + { + var s = 0d; + for (var j = 0; j < ColumnCount; j++) + { + s += Math.Abs(At(i, j)); + } + norm = Math.Max(norm, s); + } + return norm; } /// Calculates the Frobenius norm of this matrix. /// The Frobenius norm of this matrix. - public override float FrobeniusNorm() + public override double FrobeniusNorm() { var transpose = Transpose(); var aat = this * transpose; - - var norm = 0.0f; + var norm = 0d; for (var i = 0; i < RowCount; i++) { norm += aat.At(i, i); } - - norm = Convert.ToSingle(Math.Sqrt(norm)); - - return norm; + return Math.Sqrt(norm); } - /// Calculates the infinity norm of this matrix. - /// The infinity norm of this matrix. - public override float InfinityNorm() + /// + /// Returns the conjugate transpose of this matrix. + /// + /// The conjugate transpose of this matrix. + public override sealed Matrix ConjugateTranspose() { - var norm = 0.0f; - for (var i = 0; i < RowCount; i++) - { - var s = 0.0f; - for (var j = 0; j < ColumnCount; j++) - { - s += Math.Abs(At(i, j)); - } - - norm = Math.Max(norm, s); - } - - return norm; + return Transpose(); } /// diff --git a/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs b/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs index d17f4615..6454d1a5 100644 --- a/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Single/SparseMatrix.cs @@ -670,18 +670,18 @@ namespace MathNet.Numerics.LinearAlgebra.Single return new SparseMatrix(ret); } - /// Calculates the Frobenius norm of this matrix. - /// The Frobenius norm of this matrix. - public override float FrobeniusNorm() + /// Calculates the infinity norm of this matrix. + /// The infinity norm of this matrix. + public override double InfinityNorm() { - var aat = (SparseCompressedRowMatrixStorage) (this*Transpose()).Storage; - var norm = 0f; - - for (var i = 0; i < aat.RowCount; i++) + var rowPointers = _storage.RowPointers; + var values = _storage.Values; + var norm = 0d; + for (var i = 0; i < RowCount; i++) { // Get the begin / end index for the current row - var startIndex = aat.RowPointers[i]; - var endIndex = aat.RowPointers[i + 1]; + var startIndex = rowPointers[i]; + var endIndex = rowPointers[i + 1]; // Get the values for the current row if (startIndex == endIndex) @@ -690,31 +690,27 @@ namespace MathNet.Numerics.LinearAlgebra.Single continue; } + var s = 0d; for (var j = startIndex; j < endIndex; j++) { - if (i == aat.ColumnIndices[j]) - { - norm += Math.Abs(aat.Values[j]); - } + s += Math.Abs(values[j]); } + norm = Math.Max(norm, s); } - - return Convert.ToSingle(Math.Sqrt(norm)); + return norm; } - /// Calculates the infinity norm of this matrix. - /// The infinity norm of this matrix. - public override float InfinityNorm() + /// Calculates the Frobenius norm of this matrix. + /// The Frobenius norm of this matrix. + public override double FrobeniusNorm() { - var rowPointers = _storage.RowPointers; - var values = _storage.Values; - - var norm = 0f; - for (var i = 0; i < RowCount; i++) + var aat = (SparseCompressedRowMatrixStorage) (this*Transpose()).Storage; + var norm = 0d; + for (var i = 0; i < aat.RowCount; i++) { // Get the begin / end index for the current row - var startIndex = rowPointers[i]; - var endIndex = rowPointers[i + 1]; + var startIndex = aat.RowPointers[i]; + var endIndex = aat.RowPointers[i + 1]; // Get the values for the current row if (startIndex == endIndex) @@ -723,16 +719,15 @@ namespace MathNet.Numerics.LinearAlgebra.Single continue; } - var s = 0f; for (var j = startIndex; j < endIndex; j++) { - s += Math.Abs(values[j]); + if (i == aat.ColumnIndices[j]) + { + norm += Math.Abs(aat.Values[j]); + } } - - norm = Math.Max(norm, s); } - - return norm; + return Math.Sqrt(norm); } /// diff --git a/src/Numerics/Precision.Equality.cs b/src/Numerics/Precision.Equality.cs index c1ed6dfc..bca92d37 100644 --- a/src/Numerics/Precision.Equality.cs +++ b/src/Numerics/Precision.Equality.cs @@ -30,10 +30,11 @@ using System; using System.Collections.Generic; +using MathNet.Numerics.LinearAlgebra; + #if PORTABLE using System.Runtime.InteropServices; #endif -using MathNet.Numerics.LinearAlgebra; namespace MathNet.Numerics { @@ -42,6 +43,8 @@ namespace MathNet.Numerics using Complex = System.Numerics.Complex; #endif + // TODO PERF: Cache/Precompute 10^x terms + public static partial class Precision { /// @@ -116,7 +119,7 @@ namespace MathNet.Numerics // If one is almost zero, fall back to absolute equality if (Math.Abs(a) < DoublePrecision || Math.Abs(b) < DoublePrecision) { - return AlmostEqualNorm(a, b, diff, maximumError); + return Math.Abs(diff) < maximumError; } if ((a == 0 && Math.Abs(b) < maximumError) || (b == 0 && Math.Abs(a) < maximumError)) @@ -361,8 +364,7 @@ namespace MathNet.Numerics // 10^(-numberOfDecimalPlaces). We divide by two so that we have half the range // on each side of the numbers, e.g. if decimalPlaces == 2, // then 0.01 will equal between 0.005 and 0.015, but not 0.02 and not 0.00 - double decimalPlaceMagnitude = Math.Pow(10, -decimalPlaces) / 2d; - return Math.Abs(diff) < decimalPlaceMagnitude; + return Math.Abs(diff) < Math.Pow(10, -decimalPlaces) / 2d; } /// @@ -437,8 +439,7 @@ namespace MathNet.Numerics // 10^(-numberOfDecimalPlaces). We divide by two so that we have half the range // on each side of the numbers, e.g. if decimalPlaces == 2, // then 0.01 will equal between 0.005 and 0.015, but not 0.02 and not 0.00 - double decimalPlaceMagnitude = Math.Pow(10, -decimalPlaces) / 2d; - return Math.Abs(diff) < decimalPlaceMagnitude; + return Math.Abs(diff) < Math.Pow(10, -decimalPlaces) / 2d; } // If the magnitudes of the two numbers are equal to within one magnitude the numbers could potentially be equal @@ -454,8 +455,7 @@ namespace MathNet.Numerics // 10^(-numberOfDecimalPlaces). We divide by two so that we have half the range // on each side of the numbers, e.g. if decimalPlaces == 2, // then 0.01 will equal between 0.00995 and 0.01005, but not 0.0015 and not 0.0095 - double decimalPlaceMagnitude1 = Math.Pow(10, magnitudeOfMax - decimalPlaces) / 2d; - return Math.Abs(diff) < decimalPlaceMagnitude1; + return Math.Abs(diff) < Math.Pow(10, magnitudeOfMax - decimalPlaces) / 2d; } /// @@ -775,6 +775,7 @@ namespace MathNet.Numerics /// /// The first value list. /// The second value list. + /// The number of decimal places. public static bool ListAlmostEqual(this IList a, IList b, int decimalPlaces) { return ListForAll(a, b, AlmostEqual, decimalPlaces); @@ -786,6 +787,7 @@ namespace MathNet.Numerics /// /// The first value list. /// The second value list. + /// The number of decimal places. public static bool ListAlmostEqual(this IList a, IList b, int decimalPlaces) { return ListForAll(a, b, AlmostEqual, decimalPlaces); @@ -797,6 +799,7 @@ namespace MathNet.Numerics /// /// The first value list. /// The second value list. + /// The number of decimal places. public static bool ListAlmostEqual(this IList a, IList b, int decimalPlaces) { return ListForAll(a, b, AlmostEqual, decimalPlaces); @@ -808,6 +811,7 @@ namespace MathNet.Numerics /// /// The first value list. /// The second value list. + /// The number of decimal places. public static bool ListAlmostEqual(this IList a, IList b, int decimalPlaces) { return ListForAll(a, b, AlmostEqual, decimalPlaces); @@ -819,6 +823,7 @@ namespace MathNet.Numerics /// /// The first value list. /// The second value list. + /// The number of decimal places. public static bool ListAlmostEqualRelative(this IList a, IList b, int decimalPlaces) { return ListForAll(a, b, AlmostEqualRelative, decimalPlaces); @@ -830,6 +835,7 @@ namespace MathNet.Numerics /// /// The first value list. /// The second value list. + /// The number of decimal places. public static bool ListAlmostEqualRelative(this IList a, IList b, int decimalPlaces) { return ListForAll(a, b, AlmostEqualRelative, decimalPlaces); @@ -841,6 +847,7 @@ namespace MathNet.Numerics /// /// The first value list. /// The second value list. + /// The number of decimal places. public static bool ListAlmostEqualRelative(this IList a, IList b, int decimalPlaces) { return ListForAll(a, b, AlmostEqualRelative, decimalPlaces); @@ -852,6 +859,7 @@ namespace MathNet.Numerics /// /// The first value list. /// The second value list. + /// The number of decimal places. public static bool ListAlmostEqualRelative(this IList a, IList b, int decimalPlaces) { return ListForAll(a, b, AlmostEqualRelative, decimalPlaces); @@ -943,8 +951,7 @@ namespace MathNet.Numerics } /// - /// Compares two complex and determines if they are equal within - /// the specified maximum error. + /// Compares two vectors and determines if they are equal within the specified maximum error. /// /// The first value. /// The second value. @@ -956,8 +963,7 @@ namespace MathNet.Numerics } /// - /// Compares two doubles and determines if they are equal within - /// the specified maximum error. + /// Compares two vectors and determines if they are equal within the specified maximum error. /// /// The first value. /// The second value. @@ -969,8 +975,8 @@ namespace MathNet.Numerics } /// - /// Compares two doubles and determines if they are equal to within the specified number of decimal places or not, using the - /// number of decimal places as an absolute measure. + /// Compares two vectors and determines if they are equal to within the specified number + /// of decimal places or not, using the number of decimal places as an absolute measure. /// /// The first value. /// The second value. @@ -982,8 +988,8 @@ namespace MathNet.Numerics } /// - /// Compares two doubles and determines if they are equal to within the specified number of decimal places or not. If the numbers - /// are very close to zero an absolute difference is compared, otherwise the relative difference is compared. + /// Compares two vectors and determines if they are equal to within the specified number of decimal places or not. + /// If the numbers are very close to zero an absolute difference is compared, otherwise the relative difference is compared. /// /// The first value. /// The second value. @@ -994,56 +1000,54 @@ namespace MathNet.Numerics return AlmostEqualNormRelative(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), decimalPlaces); } - ///// - ///// Compares two complex and determines if they are equal within - ///// the specified maximum error. - ///// - ///// The first value. - ///// The second value. - ///// The accuracy required for being almost equal. - //public static bool AlmostEqual(this Matrix a, Matrix b, double maximumAbsoluteError) - // where T : struct, IEquatable, IFormattable - //{ - // return AlmostEqualNorm(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), maximumAbsoluteError); - //} - - ///// - ///// Compares two doubles and determines if they are equal within - ///// the specified maximum error. - ///// - ///// The first value. - ///// The second value. - ///// The accuracy required for being almost equal. - //public static bool AlmostEqualRelative(this Matrix a, Matrix b, double maximumError) - // where T : struct, IEquatable, IFormattable - //{ - // return AlmostEqualNormRelative(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), maximumError); - //} - - ///// - ///// Compares two doubles and determines if they are equal to within the specified number of decimal places or not, using the - ///// number of decimal places as an absolute measure. - ///// - ///// The first value. - ///// The second value. - ///// The number of decimal places. - //public static bool AlmostEqual(this Matrix a, Matrix b, int decimalPlaces) - // where T : struct, IEquatable, IFormattable - //{ - // return AlmostEqualNorm(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), decimalPlaces); - //} - - ///// - ///// Compares two doubles and determines if they are equal to within the specified number of decimal places or not. If the numbers - ///// are very close to zero an absolute difference is compared, otherwise the relative difference is compared. - ///// - ///// The first value. - ///// The second value. - ///// The number of decimal places. - //public static bool AlmostEqualRelative(this Matrix a, Matrix b, int decimalPlaces) - // where T : struct, IEquatable, IFormattable - //{ - // return AlmostEqualNormRelative(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), decimalPlaces); - //} + /// + /// Compares two matrices and determines if they are equal within the specified maximum error. + /// + /// The first value. + /// The second value. + /// The accuracy required for being almost equal. + public static bool AlmostEqual(this Matrix a, Matrix b, double maximumAbsoluteError) + where T : struct, IEquatable, IFormattable + { + return AlmostEqualNorm(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), maximumAbsoluteError); + } + + /// + /// Compares two matrices and determines if they are equal within the specified maximum error. + /// + /// The first value. + /// The second value. + /// The accuracy required for being almost equal. + public static bool AlmostEqualRelative(this Matrix a, Matrix b, double maximumError) + where T : struct, IEquatable, IFormattable + { + return AlmostEqualNormRelative(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), maximumError); + } + + /// + /// Compares two matrices and determines if they are equal to within the specified number + /// of decimal places or not, using the number of decimal places as an absolute measure. + /// + /// The first value. + /// The second value. + /// The number of decimal places. + public static bool AlmostEqual(this Matrix a, Matrix b, int decimalPlaces) + where T : struct, IEquatable, IFormattable + { + return AlmostEqualNorm(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), decimalPlaces); + } + + /// + /// Compares two matrices and determines if they are equal to within the specified number of decimal places or not. + /// If the numbers are very close to zero an absolute difference is compared, otherwise the relative difference is compared. + /// + /// The first value. + /// The second value. + /// The number of decimal places. + public static bool AlmostEqualRelative(this Matrix a, Matrix b, int decimalPlaces) + where T : struct, IEquatable, IFormattable + { + return AlmostEqualNormRelative(a.L2Norm(), b.L2Norm(), (a - b).L2Norm(), decimalPlaces); + } } } diff --git a/src/UnitTests/LinearAlgebraTests/Complex32/MatrixTests.cs b/src/UnitTests/LinearAlgebraTests/Complex32/MatrixTests.cs index 011394dc..5fb5214e 100644 --- a/src/UnitTests/LinearAlgebraTests/Complex32/MatrixTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Complex32/MatrixTests.cs @@ -92,13 +92,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32 public virtual void CanComputeFrobeniusNorm() { var matrix = TestMatrices["Square3x3"]; - AssertHelpers.AlmostEqualRelative(11.1427106217473f, matrix.FrobeniusNorm().Real, 6); + AssertHelpers.AlmostEqualRelative(11.1427106217473f, matrix.FrobeniusNorm(), 6); matrix = TestMatrices["Wide2x3"]; - AssertHelpers.AlmostEqualRelative(5.29055762656452f, matrix.FrobeniusNorm().Real, 6); + AssertHelpers.AlmostEqualRelative(5.29055762656452f, matrix.FrobeniusNorm(), 6); matrix = TestMatrices["Tall3x2"]; - AssertHelpers.AlmostEqualRelative(7.86574853399217, matrix.FrobeniusNorm().Real, 6); + AssertHelpers.AlmostEqualRelative(7.86574853399217, matrix.FrobeniusNorm(), 6); } /// @@ -108,13 +108,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32 public virtual void CanComputeInfinityNorm() { var matrix = TestMatrices["Square3x3"]; - AssertHelpers.AlmostEqualRelative(16.7777033f, matrix.InfinityNorm().Real, 6); + AssertHelpers.AlmostEqualRelative(16.7777033f, matrix.InfinityNorm(), 6); matrix = TestMatrices["Wide2x3"]; - AssertHelpers.AlmostEqualRelative(7.3514039f, matrix.InfinityNorm().Real, 6); + AssertHelpers.AlmostEqualRelative(7.3514039f, matrix.InfinityNorm(), 6); matrix = TestMatrices["Tall3x2"]; - AssertHelpers.AlmostEqualRelative(10.1023756f, matrix.InfinityNorm().Real, 6); + AssertHelpers.AlmostEqualRelative(10.1023756f, matrix.InfinityNorm(), 6); } /// @@ -124,13 +124,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32 public virtual void CanComputeL1Norm() { var matrix = TestMatrices["Square3x3"]; - AssertHelpers.AlmostEqualRelative(12.5401248f, matrix.L1Norm().Real, 7); + AssertHelpers.AlmostEqualRelative(12.5401248f, matrix.L1Norm(), 7); matrix = TestMatrices["Wide2x3"]; - AssertHelpers.AlmostEqualRelative(5.8647971f, matrix.L1Norm().Real, 7); + AssertHelpers.AlmostEqualRelative(5.8647971f, matrix.L1Norm(), 7); matrix = TestMatrices["Tall3x2"]; - AssertHelpers.AlmostEqualRelative(9.4933860f, matrix.L1Norm().Real, 7); + AssertHelpers.AlmostEqualRelative(9.4933860f, matrix.L1Norm(), 7); } /// @@ -140,12 +140,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32 public virtual void CanComputeL2Norm() { var matrix = TestMatrices["Square3x3"]; - AssertHelpers.AlmostEqualRelative(10.6381752f, matrix.L2Norm().Real, 6); + AssertHelpers.AlmostEqualRelative(10.6381752f, matrix.L2Norm(), 6); matrix = TestMatrices["Wide2x3"]; - AssertHelpers.AlmostEqualRelative(5.2058554f, matrix.L2Norm().Real, 6); + AssertHelpers.AlmostEqualRelative(5.2058554f, matrix.L2Norm(), 6); + matrix = TestMatrices["Tall3x2"]; - AssertHelpers.AlmostEqualRelative(7.3582664f, matrix.L2Norm().Real, 6); + AssertHelpers.AlmostEqualRelative(7.3582664f, matrix.L2Norm(), 6); } ///