From 390cae2177623f40a15ce824e8cb767dab0d165a Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sun, 8 Sep 2013 18:42:06 +0200 Subject: [PATCH] LA: Simplify Gram-Schmidt decomposition architecture --- .../LinearAlgebra/Complex/DenseMatrix.cs | 2 +- .../Complex/Factorization/DenseGramSchmidt.cs | 57 +++++---------- .../Complex/Factorization/GramSchmidt.cs | 15 +++- .../Complex/Factorization/UserGramSchmidt.cs | 69 +++++++------------ src/Numerics/LinearAlgebra/Complex/Matrix.cs | 2 +- .../LinearAlgebra/Complex32/DenseMatrix.cs | 2 +- .../Factorization/DenseGramSchmidt.cs | 57 +++++---------- .../Complex32/Factorization/GramSchmidt.cs | 15 +++- .../Factorization/UserGramSchmidt.cs | 69 +++++++------------ .../LinearAlgebra/Complex32/Matrix.cs | 2 +- .../LinearAlgebra/Double/DenseMatrix.cs | 2 +- .../Double/Factorization/DenseGramSchmidt.cs | 57 +++++---------- .../Double/Factorization/GramSchmidt.cs | 16 +++-- .../Double/Factorization/UserGramSchmidt.cs | 67 +++++++----------- src/Numerics/LinearAlgebra/Double/Matrix.cs | 2 +- .../Factorization/GramSchmidt.cs | 11 ++- .../LinearAlgebra/Single/DenseMatrix.cs | 2 +- .../Single/Factorization/DenseGramSchmidt.cs | 57 +++++---------- .../Single/Factorization/GramSchmidt.cs | 16 +++-- .../Single/Factorization/UserGramSchmidt.cs | 67 +++++++----------- src/Numerics/LinearAlgebra/Single/Matrix.cs | 2 +- .../Complex/Factorization/GramSchmidtTests.cs | 13 +--- .../Factorization/UserGramSchmidtTests.cs | 17 ++--- .../Factorization/GramSchmidtTests.cs | 13 +--- .../Factorization/UserGramSchmidtTests.cs | 19 ++--- .../Double/Factorization/GramSchmidtTests.cs | 13 +--- .../Factorization/UserGramSchmidtTests.cs | 18 ++--- .../Single/Factorization/GramSchmidtTests.cs | 13 +--- .../Factorization/UserGramSchmidtTests.cs | 18 ++--- 29 files changed, 257 insertions(+), 456 deletions(-) diff --git a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs index cb6b4391..ce1eea7c 100644 --- a/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs @@ -1026,7 +1026,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex public override GramSchmidt GramSchmidt() { - return new DenseGramSchmidt(this); + return DenseGramSchmidt.Create(this); } public override Svd Svd(bool computeVectors) diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/DenseGramSchmidt.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/DenseGramSchmidt.cs index c441e3be..a05ceda7 100644 --- a/src/Numerics/LinearAlgebra/Complex/Factorization/DenseGramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Complex/Factorization/DenseGramSchmidt.cs @@ -4,7 +4,7 @@ // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // -// Copyright (c) 2009-2010 Math.NET +// Copyright (c) 2009-2013 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -28,10 +28,9 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Factorization; using MathNet.Numerics.Properties; -using System; -using MathNet.Numerics.Providers.LinearAlgebra; namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization { @@ -49,13 +48,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization /// /// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization. /// - public class DenseGramSchmidt : GramSchmidt + public sealed class DenseGramSchmidt : GramSchmidt { - /// - /// used for QR solve - /// - private readonly ILinearAlgebraProvider _provider = new ManagedLinearAlgebraProvider(); - /// /// Initializes a new instance of the class. This object creates an unitary matrix /// using the modified Gram-Schmidt method. @@ -64,21 +58,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization /// If is null. /// If row count is less then column count /// If is rank deficient - public DenseGramSchmidt(DenseMatrix matrix) + public static DenseGramSchmidt Create(DenseMatrix matrix) { - if (matrix == null) - { - throw new ArgumentNullException("matrix"); - } - if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch(matrix); } - Q = matrix.Clone(); - MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); - Factorize(((DenseMatrix)Q).Values, Q.RowCount, Q.ColumnCount, ((DenseMatrix)MatrixR).Values); + var q = (DenseMatrix)matrix.Clone(); + var r = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount); + Factorize(q.Values, q.RowCount, q.ColumnCount, r.Values); + + return new DenseGramSchmidt(q, r); + } + + DenseGramSchmidt(Matrix q, Matrix rFull) + : base(q, rFull) + { } /// @@ -138,17 +134,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization /// The left hand side , X. public override void Solve(Matrix input, Matrix result) { - // Check for proper arguments. - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // The solution X should have the same number of columns as B if (input.ColumnCount != result.ColumnCount) { @@ -179,7 +164,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization throw new NotSupportedException("Can only do GramSchmidt factorization for dense matrices at the moment."); } - _provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin); + Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin); } /// @@ -189,16 +174,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization /// The left hand side , x. public override void Solve(Vector input, Vector result) { - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // Ax=b where A is an m x n matrix // Check that b is a column vector with m entries if (Q.RowCount != input.Count) @@ -224,7 +199,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment."); } - _provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin); + Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin); } } } diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/GramSchmidt.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/GramSchmidt.cs index f57777aa..f5bfeda2 100644 --- a/src/Numerics/LinearAlgebra/Complex/Factorization/GramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Complex/Factorization/GramSchmidt.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com -// Copyright (c) 2009-2010 Math.NET +// +// Copyright (c) 2009-2013 Math.NET +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,12 +28,12 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Factorization; +using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization { - using System; - using Properties; #if NOSYSNUMERICS using Complex = Numerics.Complex; @@ -46,6 +50,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization /// public abstract class GramSchmidt : GramSchmidt { + protected GramSchmidt(Matrix q, Matrix rFull) + : base(q, rFull) + { + } + /// /// Gets the absolute determinant value of the matrix for which the QR matrix was computed. /// diff --git a/src/Numerics/LinearAlgebra/Complex/Factorization/UserGramSchmidt.cs b/src/Numerics/LinearAlgebra/Complex/Factorization/UserGramSchmidt.cs index cd30749e..6e7e873a 100644 --- a/src/Numerics/LinearAlgebra/Complex/Factorization/UserGramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Complex/Factorization/UserGramSchmidt.cs @@ -4,7 +4,7 @@ // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // -// Copyright (c) 2009-2010 Math.NET +// Copyright (c) 2009-2013 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -28,8 +28,8 @@ // OTHER DEALINGS IN THE SOFTWARE. // -using MathNet.Numerics.Properties; using System; +using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization { @@ -47,7 +47,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization /// /// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization. /// - public class UserGramSchmidt : GramSchmidt + public sealed class UserGramSchmidt : GramSchmidt { /// /// Initializes a new instance of the class. This object creates an unitary matrix @@ -57,51 +57,53 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization /// If is null. /// If row count is less then column count /// If is rank deficient - public UserGramSchmidt(Matrix matrix) + public static UserGramSchmidt Create(Matrix matrix) { - if (matrix == null) - { - throw new ArgumentNullException("matrix"); - } - if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch(matrix); } - Q = matrix.Clone(); - MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); + var q = matrix.Clone(); + var r = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); - for (var k = 0; k < Q.ColumnCount; k++) + for (var k = 0; k < q.ColumnCount; k++) { - var norm = Q.Column(k).L2Norm(); + var norm = q.Column(k).L2Norm(); if (norm == 0.0) { throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient); } - MatrixR.At(k, k, norm); - for (var i = 0; i < Q.RowCount; i++) + r.At(k, k, norm); + for (var i = 0; i < q.RowCount; i++) { - Q.At(i, k, Q.At(i, k) / norm); + q.At(i, k, q.At(i, k) / norm); } - for (var j = k + 1; j < Q.ColumnCount; j++) + for (var j = k + 1; j < q.ColumnCount; j++) { var dot = Complex.Zero; - for (int i = 0; i < Q.RowCount; i++) + for (int i = 0; i < q.RowCount; i++) { - dot += Q.Column(k)[i].Conjugate() * Q.Column(j)[i]; + dot += q.Column(k)[i].Conjugate() * q.Column(j)[i]; } - MatrixR.At(k, j, dot); - for (var i = 0; i < Q.RowCount; i++) + r.At(k, j, dot); + for (var i = 0; i < q.RowCount; i++) { - var value = Q.At(i, j) - (Q.At(i, k) * dot); - Q.At(i, j, value); + var value = q.At(i, j) - (q.At(i, k) * dot); + q.At(i, j, value); } } } + + return new UserGramSchmidt(q, r); + } + + UserGramSchmidt(Matrix q, Matrix rFull) + : base(q, rFull) + { } /// @@ -111,17 +113,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization /// The left hand side , X. public override void Solve(Matrix input, Matrix result) { - // Check for proper arguments. - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // The solution X should have the same number of columns as B if (input.ColumnCount != result.ColumnCount) { @@ -196,16 +187,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization /// The left hand side , x. public override void Solve(Vector input, Vector result) { - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // Ax=b where A is an m x n matrix // Check that b is a column vector with m entries if (Q.RowCount != input.Count) diff --git a/src/Numerics/LinearAlgebra/Complex/Matrix.cs b/src/Numerics/LinearAlgebra/Complex/Matrix.cs index 96b1090d..2fde3cc5 100644 --- a/src/Numerics/LinearAlgebra/Complex/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/Matrix.cs @@ -475,7 +475,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex public override GramSchmidt GramSchmidt() { - return new UserGramSchmidt(this); + return UserGramSchmidt.Create(this); } public override Svd Svd(bool computeVectors) diff --git a/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs index 8c36d9cf..1d6f10d1 100644 --- a/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs @@ -1021,7 +1021,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 public override GramSchmidt GramSchmidt() { - return new DenseGramSchmidt(this); + return DenseGramSchmidt.Create(this); } public override Svd Svd(bool computeVectors) diff --git a/src/Numerics/LinearAlgebra/Complex32/Factorization/DenseGramSchmidt.cs b/src/Numerics/LinearAlgebra/Complex32/Factorization/DenseGramSchmidt.cs index 0901e869..8c638910 100644 --- a/src/Numerics/LinearAlgebra/Complex32/Factorization/DenseGramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Complex32/Factorization/DenseGramSchmidt.cs @@ -4,7 +4,7 @@ // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // -// Copyright (c) 2009-2010 Math.NET +// Copyright (c) 2009-2013 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -28,10 +28,9 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Factorization; using MathNet.Numerics.Properties; -using System; -using MathNet.Numerics.Providers.LinearAlgebra; namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization { @@ -44,13 +43,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization /// /// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization. /// - public class DenseGramSchmidt : GramSchmidt + public sealed class DenseGramSchmidt : GramSchmidt { - /// - /// used for QR solve - /// - private readonly ILinearAlgebraProvider _provider = new ManagedLinearAlgebraProvider(); - /// /// Initializes a new instance of the class. This object creates an unitary matrix /// using the modified Gram-Schmidt method. @@ -59,21 +53,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization /// If is null. /// If row count is less then column count /// If is rank deficient - public DenseGramSchmidt(DenseMatrix matrix) + public static DenseGramSchmidt Create(DenseMatrix matrix) { - if (matrix == null) - { - throw new ArgumentNullException("matrix"); - } - if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch(matrix); } - Q = matrix.Clone(); - MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); - Factorize(((DenseMatrix)Q).Values, Q.RowCount, Q.ColumnCount, ((DenseMatrix)MatrixR).Values); + var q = (DenseMatrix)matrix.Clone(); + var r = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount); + Factorize(q.Values, q.RowCount, q.ColumnCount, r.Values); + + return new DenseGramSchmidt(q, r); + } + + DenseGramSchmidt(Matrix q, Matrix rFull) + : base(q, rFull) + { } /// @@ -133,17 +129,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization /// The left hand side , X. public override void Solve(Matrix input, Matrix result) { - // Check for proper arguments. - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // The solution X should have the same number of columns as B if (input.ColumnCount != result.ColumnCount) { @@ -174,7 +159,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization throw new NotSupportedException("Can only do GramSchmidt factorization for dense matrices at the moment."); } - _provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin); + Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin); } /// @@ -184,16 +169,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization /// The left hand side , x. public override void Solve(Vector input, Vector result) { - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // Ax=b where A is an m x n matrix // Check that b is a column vector with m entries if (Q.RowCount != input.Count) @@ -219,7 +194,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment."); } - _provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin); + Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin); } } } diff --git a/src/Numerics/LinearAlgebra/Complex32/Factorization/GramSchmidt.cs b/src/Numerics/LinearAlgebra/Complex32/Factorization/GramSchmidt.cs index 0354c4d4..33bcd896 100644 --- a/src/Numerics/LinearAlgebra/Complex32/Factorization/GramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Complex32/Factorization/GramSchmidt.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com -// Copyright (c) 2009-2010 Math.NET +// +// Copyright (c) 2009-2013 Math.NET +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,13 +28,13 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Factorization; +using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization { - using System; using Numerics; - using Properties; /// /// A class which encapsulates the functionality of the QR decomposition Modified Gram-Schmidt Orthogonalization. @@ -41,6 +45,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization /// public abstract class GramSchmidt : GramSchmidt { + protected GramSchmidt(Matrix q, Matrix rFull) + : base(q, rFull) + { + } + /// /// Gets the absolute determinant value of the matrix for which the QR matrix was computed. /// diff --git a/src/Numerics/LinearAlgebra/Complex32/Factorization/UserGramSchmidt.cs b/src/Numerics/LinearAlgebra/Complex32/Factorization/UserGramSchmidt.cs index e2ac7284..e9614d9b 100644 --- a/src/Numerics/LinearAlgebra/Complex32/Factorization/UserGramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Complex32/Factorization/UserGramSchmidt.cs @@ -4,7 +4,7 @@ // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // -// Copyright (c) 2009-2010 Math.NET +// Copyright (c) 2009-2013 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -28,8 +28,8 @@ // OTHER DEALINGS IN THE SOFTWARE. // -using MathNet.Numerics.Properties; using System; +using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization { @@ -42,7 +42,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization /// /// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization. /// - public class UserGramSchmidt : GramSchmidt + public sealed class UserGramSchmidt : GramSchmidt { /// /// Initializes a new instance of the class. This object creates an unitary matrix @@ -52,51 +52,53 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization /// If is null. /// If row count is less then column count /// If is rank deficient - public UserGramSchmidt(Matrix matrix) + public static UserGramSchmidt Create(Matrix matrix) { - if (matrix == null) - { - throw new ArgumentNullException("matrix"); - } - if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch(matrix); } - Q = matrix.Clone(); - MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); + var q = matrix.Clone(); + var r = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); - for (var k = 0; k < Q.ColumnCount; k++) + for (var k = 0; k < q.ColumnCount; k++) { - var norm = Q.Column(k).L2Norm().Real; + var norm = q.Column(k).L2Norm().Real; if (norm == 0.0f) { throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient); } - MatrixR.At(k, k, norm); - for (var i = 0; i < Q.RowCount; i++) + r.At(k, k, norm); + for (var i = 0; i < q.RowCount; i++) { - Q.At(i, k, Q.At(i, k) / norm); + q.At(i, k, q.At(i, k) / norm); } - for (var j = k + 1; j < Q.ColumnCount; j++) + for (var j = k + 1; j < q.ColumnCount; j++) { var dot = Complex32.Zero; - for (int i = 0; i < Q.RowCount; i++) + for (int i = 0; i < q.RowCount; i++) { - dot += Q.Column(k)[i].Conjugate() * Q.Column(j)[i]; + dot += q.Column(k)[i].Conjugate() * q.Column(j)[i]; } - MatrixR.At(k, j, dot); - for (var i = 0; i < Q.RowCount; i++) + r.At(k, j, dot); + for (var i = 0; i < q.RowCount; i++) { - var value = Q.At(i, j) - (Q.At(i, k) * dot); - Q.At(i, j, value); + var value = q.At(i, j) - (q.At(i, k) * dot); + q.At(i, j, value); } } } + + return new UserGramSchmidt(q, r); + } + + UserGramSchmidt(Matrix q, Matrix rFull) + : base(q, rFull) + { } /// @@ -106,17 +108,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization /// The left hand side , X. public override void Solve(Matrix input, Matrix result) { - // Check for proper arguments. - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // The solution X should have the same number of columns as B if (input.ColumnCount != result.ColumnCount) { @@ -191,16 +182,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization /// The left hand side , x. public override void Solve(Vector input, Vector result) { - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // Ax=b where A is an m x n matrix // Check that b is a column vector with m entries if (Q.RowCount != input.Count) diff --git a/src/Numerics/LinearAlgebra/Complex32/Matrix.cs b/src/Numerics/LinearAlgebra/Complex32/Matrix.cs index 4ba57d64..156964b6 100644 --- a/src/Numerics/LinearAlgebra/Complex32/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/Matrix.cs @@ -470,7 +470,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 public override GramSchmidt GramSchmidt() { - return new UserGramSchmidt(this); + return UserGramSchmidt.Create(this); } public override Svd Svd(bool computeVectors) diff --git a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs index 645650d3..87d3480e 100644 --- a/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Double/DenseMatrix.cs @@ -1052,7 +1052,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double public override GramSchmidt GramSchmidt() { - return new DenseGramSchmidt(this); + return DenseGramSchmidt.Create(this); } public override Svd Svd(bool computeVectors) diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/DenseGramSchmidt.cs b/src/Numerics/LinearAlgebra/Double/Factorization/DenseGramSchmidt.cs index 44adebb0..70bf4cb8 100644 --- a/src/Numerics/LinearAlgebra/Double/Factorization/DenseGramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Double/Factorization/DenseGramSchmidt.cs @@ -4,7 +4,7 @@ // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // -// Copyright (c) 2009-2010 Math.NET +// Copyright (c) 2009-2013 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -28,10 +28,9 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Factorization; using MathNet.Numerics.Properties; -using System; -using MathNet.Numerics.Providers.LinearAlgebra; namespace MathNet.Numerics.LinearAlgebra.Double.Factorization { @@ -42,13 +41,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization /// /// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization. /// - public class DenseGramSchmidt : GramSchmidt + public sealed class DenseGramSchmidt : GramSchmidt { - /// - /// used for QR solve - /// - private readonly ILinearAlgebraProvider _provider = new ManagedLinearAlgebraProvider(); - /// /// Initializes a new instance of the class. This object creates an orthogonal matrix /// using the modified Gram-Schmidt method. @@ -57,21 +51,23 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization /// If is null. /// If row count is less then column count /// If is rank deficient - public DenseGramSchmidt(DenseMatrix matrix) + public static DenseGramSchmidt Create(DenseMatrix matrix) { - if (matrix == null) - { - throw new ArgumentNullException("matrix"); - } - if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch(matrix); } - Q = matrix.Clone(); - MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); - Factorize(((DenseMatrix)Q).Values, Q.RowCount, Q.ColumnCount, ((DenseMatrix)MatrixR).Values); + var q = (DenseMatrix)matrix.Clone(); + var r = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount); + Factorize(q.Values, q.RowCount, q.ColumnCount, r.Values); + + return new DenseGramSchmidt(q, r); + } + + DenseGramSchmidt(Matrix q, Matrix rFull) + : base(q, rFull) + { } /// @@ -131,17 +127,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization /// The left hand side , X. public override void Solve(Matrix input, Matrix result) { - // Check for proper arguments. - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // The solution X should have the same number of columns as B if (input.ColumnCount != result.ColumnCount) { @@ -172,7 +157,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization throw new NotSupportedException("Can only do GramSchmidt factorization for dense matrices at the moment."); } - _provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin); + Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin); } /// @@ -182,16 +167,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization /// The left hand side , x. public override void Solve(Vector input, Vector result) { - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // Ax=b where A is an m x n matrix // Check that b is a column vector with m entries if (Q.RowCount != input.Count) @@ -217,7 +192,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment."); } - _provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin); + Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin); } } } diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/GramSchmidt.cs b/src/Numerics/LinearAlgebra/Double/Factorization/GramSchmidt.cs index d4305f67..1e1b34a2 100644 --- a/src/Numerics/LinearAlgebra/Double/Factorization/GramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Double/Factorization/GramSchmidt.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com -// Copyright (c) 2009-2010 Math.NET +// +// Copyright (c) 2009-2013 Math.NET +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,13 +28,12 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Factorization; +using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra.Double.Factorization { - using System; - using Properties; - /// /// A class which encapsulates the functionality of the QR decomposition Modified Gram-Schmidt Orthogonalization. /// Any real square matrix A may be decomposed as A = QR where Q is an orthogonal mxn matrix and R is an nxn upper triangular matrix. @@ -40,6 +43,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization /// public abstract class GramSchmidt : GramSchmidt { + protected GramSchmidt(Matrix q, Matrix rFull) + : base(q,rFull) + { + } + /// /// Gets the absolute determinant value of the matrix for which the QR matrix was computed. /// diff --git a/src/Numerics/LinearAlgebra/Double/Factorization/UserGramSchmidt.cs b/src/Numerics/LinearAlgebra/Double/Factorization/UserGramSchmidt.cs index a0ec61c3..ba902841 100644 --- a/src/Numerics/LinearAlgebra/Double/Factorization/UserGramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Double/Factorization/UserGramSchmidt.cs @@ -4,7 +4,7 @@ // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // -// Copyright (c) 2009-2010 Math.NET +// Copyright (c) 2009-2013 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -28,8 +28,8 @@ // OTHER DEALINGS IN THE SOFTWARE. // -using MathNet.Numerics.Properties; using System; +using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra.Double.Factorization { @@ -40,7 +40,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization /// /// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization. /// - public class UserGramSchmidt : GramSchmidt + public sealed class UserGramSchmidt : GramSchmidt { /// /// Initializes a new instance of the class. This object creates an orthogonal matrix @@ -50,46 +50,48 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization /// If is null. /// If row count is less then column count /// If is rank deficient - public UserGramSchmidt(Matrix matrix) + public static UserGramSchmidt Create(Matrix matrix) { - if (matrix == null) - { - throw new ArgumentNullException("matrix"); - } - if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch(matrix); } - Q = matrix.Clone(); - MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); + var q = matrix.Clone(); + var r = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); - for (var k = 0; k < Q.ColumnCount; k++) + for (var k = 0; k < q.ColumnCount; k++) { - var norm = Q.Column(k).L2Norm(); + var norm = q.Column(k).L2Norm(); if (norm == 0.0) { throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient); } - MatrixR.At(k, k, norm); - for (var i = 0; i < Q.RowCount; i++) + r.At(k, k, norm); + for (var i = 0; i < q.RowCount; i++) { - Q.At(i, k, Q.At(i, k) / norm); + q.At(i, k, q.At(i, k) / norm); } - for (var j = k + 1; j < Q.ColumnCount; j++) + for (var j = k + 1; j < q.ColumnCount; j++) { - var dot = Q.Column(k).DotProduct(Q.Column(j)); - MatrixR.At(k, j, dot); - for (var i = 0; i < Q.RowCount; i++) + var dot = q.Column(k).DotProduct(q.Column(j)); + r.At(k, j, dot); + for (var i = 0; i < q.RowCount; i++) { - var value = Q.At(i, j) - (Q.At(i, k) * dot); - Q.At(i, j, value); + var value = q.At(i, j) - (q.At(i, k) * dot); + q.At(i, j, value); } } } + + return new UserGramSchmidt(q, r); + } + + UserGramSchmidt(Matrix q, Matrix rFull) + : base(q, rFull) + { } /// @@ -99,17 +101,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization /// The left hand side , X. public override void Solve(Matrix input, Matrix result) { - // Check for proper arguments. - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // The solution X should have the same number of columns as B if (input.ColumnCount != result.ColumnCount) { @@ -184,16 +175,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization /// The left hand side , x. public override void Solve(Vector input, Vector result) { - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // Ax=b where A is an m x n matrix // Check that b is a column vector with m entries if (Q.RowCount != input.Count) diff --git a/src/Numerics/LinearAlgebra/Double/Matrix.cs b/src/Numerics/LinearAlgebra/Double/Matrix.cs index e4b5d074..5ad949dd 100644 --- a/src/Numerics/LinearAlgebra/Double/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Double/Matrix.cs @@ -476,7 +476,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double public override GramSchmidt GramSchmidt() { - return new UserGramSchmidt(this); + return UserGramSchmidt.Create(this); } public override Svd Svd(bool computeVectors) diff --git a/src/Numerics/LinearAlgebra/Factorization/GramSchmidt.cs b/src/Numerics/LinearAlgebra/Factorization/GramSchmidt.cs index 68b09636..1cb59e1b 100644 --- a/src/Numerics/LinearAlgebra/Factorization/GramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Factorization/GramSchmidt.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com -// Copyright (c) 2009-2010 Math.NET +// +// Copyright (c) 2009-2013 Math.NET +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -39,5 +43,10 @@ namespace MathNet.Numerics.LinearAlgebra.Factorization public abstract class GramSchmidt : QR where T : struct, IEquatable, IFormattable { + protected GramSchmidt(Matrix q, Matrix rFull) + { + Q = q; + MatrixR = rFull; + } } } diff --git a/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs b/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs index 99b1c773..88d2cb11 100644 --- a/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs +++ b/src/Numerics/LinearAlgebra/Single/DenseMatrix.cs @@ -1052,7 +1052,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single public override GramSchmidt GramSchmidt() { - return new DenseGramSchmidt(this); + return DenseGramSchmidt.Create(this); } public override Svd Svd(bool computeVectors) diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/DenseGramSchmidt.cs b/src/Numerics/LinearAlgebra/Single/Factorization/DenseGramSchmidt.cs index 16579149..c5b803ff 100644 --- a/src/Numerics/LinearAlgebra/Single/Factorization/DenseGramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Single/Factorization/DenseGramSchmidt.cs @@ -4,7 +4,7 @@ // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // -// Copyright (c) 2009-2010 Math.NET +// Copyright (c) 2009-2013 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -28,10 +28,9 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Factorization; using MathNet.Numerics.Properties; -using System; -using MathNet.Numerics.Providers.LinearAlgebra; namespace MathNet.Numerics.LinearAlgebra.Single.Factorization { @@ -42,13 +41,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization /// /// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization. /// - public class DenseGramSchmidt : GramSchmidt + public sealed class DenseGramSchmidt : GramSchmidt { - /// - /// used for QR solve - /// - private readonly ILinearAlgebraProvider _provider = new ManagedLinearAlgebraProvider(); - /// /// Initializes a new instance of the class. This object creates an orthogonal matrix /// using the modified Gram-Schmidt method. @@ -57,21 +51,23 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization /// If is null. /// If row count is less then column count /// If is rank deficient - public DenseGramSchmidt(DenseMatrix matrix) + public static DenseGramSchmidt Create(DenseMatrix matrix) { - if (matrix == null) - { - throw new ArgumentNullException("matrix"); - } - if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch(matrix); } - Q = matrix.Clone(); - MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); - Factorize(((DenseMatrix)Q).Values, Q.RowCount, Q.ColumnCount, ((DenseMatrix)MatrixR).Values); + var q = (DenseMatrix)matrix.Clone(); + var r = new DenseMatrix(matrix.ColumnCount, matrix.ColumnCount); + Factorize(q.Values, q.RowCount, q.ColumnCount, r.Values); + + return new DenseGramSchmidt(q, r); + } + + DenseGramSchmidt(Matrix q, Matrix rFull) + : base(q, rFull) + { } /// @@ -131,17 +127,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization /// The left hand side , X. public override void Solve(Matrix input, Matrix result) { - // Check for proper arguments. - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // The solution X should have the same number of columns as B if (input.ColumnCount != result.ColumnCount) { @@ -172,7 +157,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization throw new NotSupportedException("Can only do GramSchmidt factorization for dense matrices at the moment."); } - _provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin); + Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, input.ColumnCount, dresult.Values, QRMethod.Thin); } /// @@ -182,16 +167,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization /// The left hand side , x. public override void Solve(Vector input, Vector result) { - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // Ax=b where A is an m x n matrix // Check that b is a column vector with m entries if (Q.RowCount != input.Count) @@ -217,7 +192,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment."); } - _provider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin); + Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)Q).Values, ((DenseMatrix)MatrixR).Values, Q.RowCount, MatrixR.ColumnCount, null, dinput.Values, 1, dresult.Values, QRMethod.Thin); } } } diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/GramSchmidt.cs b/src/Numerics/LinearAlgebra/Single/Factorization/GramSchmidt.cs index 9b26dc26..f58ae735 100644 --- a/src/Numerics/LinearAlgebra/Single/Factorization/GramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Single/Factorization/GramSchmidt.cs @@ -3,7 +3,9 @@ // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com -// Copyright (c) 2009-2010 Math.NET +// +// Copyright (c) 2009-2013 Math.NET +// // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without @@ -12,8 +14,10 @@ // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,13 +28,12 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Factorization; +using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra.Single.Factorization { - using System; - using Properties; - /// /// A class which encapsulates the functionality of the QR decomposition Modified Gram-Schmidt Orthogonalization. /// Any real square matrix A may be decomposed as A = QR where Q is an orthogonal mxn matrix and R is an nxn upper triangular matrix. @@ -40,6 +43,11 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization /// public abstract class GramSchmidt : GramSchmidt { + protected GramSchmidt(Matrix q, Matrix rFull) + : base(q, rFull) + { + } + /// /// Gets the absolute determinant value of the matrix for which the QR matrix was computed. /// diff --git a/src/Numerics/LinearAlgebra/Single/Factorization/UserGramSchmidt.cs b/src/Numerics/LinearAlgebra/Single/Factorization/UserGramSchmidt.cs index 21773ed0..bf983bdd 100644 --- a/src/Numerics/LinearAlgebra/Single/Factorization/UserGramSchmidt.cs +++ b/src/Numerics/LinearAlgebra/Single/Factorization/UserGramSchmidt.cs @@ -4,7 +4,7 @@ // http://github.com/mathnet/mathnet-numerics // http://mathnetnumerics.codeplex.com // -// Copyright (c) 2009-2010 Math.NET +// Copyright (c) 2009-2013 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -28,8 +28,8 @@ // OTHER DEALINGS IN THE SOFTWARE. // -using MathNet.Numerics.Properties; using System; +using MathNet.Numerics.Properties; namespace MathNet.Numerics.LinearAlgebra.Single.Factorization { @@ -40,7 +40,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization /// /// The computation of the QR decomposition is done at construction time by modified Gram-Schmidt Orthogonalization. /// - public class UserGramSchmidt : GramSchmidt + public sealed class UserGramSchmidt : GramSchmidt { /// /// Initializes a new instance of the class. This object creates an orthogonal matrix @@ -50,46 +50,48 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization /// If is null. /// If row count is less then column count /// If is rank deficient - public UserGramSchmidt(Matrix matrix) + public static UserGramSchmidt Create(Matrix matrix) { - if (matrix == null) - { - throw new ArgumentNullException("matrix"); - } - if (matrix.RowCount < matrix.ColumnCount) { throw Matrix.DimensionsDontMatch(matrix); } - Q = matrix.Clone(); - MatrixR = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); + var q = matrix.Clone(); + var r = matrix.CreateMatrix(matrix.ColumnCount, matrix.ColumnCount); - for (var k = 0; k < Q.ColumnCount; k++) + for (var k = 0; k < q.ColumnCount; k++) { - var norm = Q.Column(k).L2Norm(); + var norm = q.Column(k).L2Norm(); if (norm == 0.0) { throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient); } - MatrixR.At(k, k, norm); - for (var i = 0; i < Q.RowCount; i++) + r.At(k, k, norm); + for (var i = 0; i < q.RowCount; i++) { - Q.At(i, k, Q.At(i, k) / norm); + q.At(i, k, q.At(i, k) / norm); } - for (var j = k + 1; j < Q.ColumnCount; j++) + for (var j = k + 1; j < q.ColumnCount; j++) { - var dot = Q.Column(k).DotProduct(Q.Column(j)); - MatrixR.At(k, j, dot); - for (var i = 0; i < Q.RowCount; i++) + var dot = q.Column(k).DotProduct(q.Column(j)); + r.At(k, j, dot); + for (var i = 0; i < q.RowCount; i++) { - var value = Q.At(i, j) - (Q.At(i, k) * dot); - Q.At(i, j, value); + var value = q.At(i, j) - (q.At(i, k) * dot); + q.At(i, j, value); } } } + + return new UserGramSchmidt(q, r); + } + + UserGramSchmidt(Matrix q, Matrix rFull) + : base(q, rFull) + { } /// @@ -99,17 +101,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization /// The left hand side , X. public override void Solve(Matrix input, Matrix result) { - // Check for proper arguments. - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // The solution X should have the same number of columns as B if (input.ColumnCount != result.ColumnCount) { @@ -184,16 +175,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization /// The left hand side , x. public override void Solve(Vector input, Vector result) { - if (input == null) - { - throw new ArgumentNullException("input"); - } - - if (result == null) - { - throw new ArgumentNullException("result"); - } - // Ax=b where A is an m x n matrix // Check that b is a column vector with m entries if (Q.RowCount != input.Count) diff --git a/src/Numerics/LinearAlgebra/Single/Matrix.cs b/src/Numerics/LinearAlgebra/Single/Matrix.cs index 109d9419..8ba5eb8e 100644 --- a/src/Numerics/LinearAlgebra/Single/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Single/Matrix.cs @@ -476,7 +476,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single public override GramSchmidt GramSchmidt() { - return new UserGramSchmidt(this); + return UserGramSchmidt.Create(this); } public override Svd Svd(bool computeVectors) diff --git a/src/UnitTests/LinearAlgebraTests/Complex/Factorization/GramSchmidtTests.cs b/src/UnitTests/LinearAlgebraTests/Complex/Factorization/GramSchmidtTests.cs index 861051f4..e154f359 100644 --- a/src/UnitTests/LinearAlgebraTests/Complex/Factorization/GramSchmidtTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Complex/Factorization/GramSchmidtTests.cs @@ -24,10 +24,10 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Complex; using MathNet.Numerics.LinearAlgebra.Complex.Factorization; using NUnit.Framework; -using System; namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization { @@ -38,22 +38,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization /// public class GramSchmidtTests { - /// - /// Constructor with null throws ArgumentNullException. - /// - [Test] - public void ConstructorNullThrowsArgumentNullException() - { - Assert.Throws(() => new DenseGramSchmidt(null)); - } - /// /// Constructor with wide matrix throws ArgumentException. /// [Test] public void ConstructorWideMatrixThrowsInvalidMatrixOperationException() { - Assert.Throws(() => new DenseGramSchmidt(new DenseMatrix(3, 4))); + Assert.Throws(() => DenseGramSchmidt.Create(new DenseMatrix(3, 4))); } /// diff --git a/src/UnitTests/LinearAlgebraTests/Complex/Factorization/UserGramSchmidtTests.cs b/src/UnitTests/LinearAlgebraTests/Complex/Factorization/UserGramSchmidtTests.cs index 9b249b43..0af16ed7 100644 --- a/src/UnitTests/LinearAlgebraTests/Complex/Factorization/UserGramSchmidtTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Complex/Factorization/UserGramSchmidtTests.cs @@ -24,33 +24,26 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; +using MathNet.Numerics.LinearAlgebra.Complex.Factorization; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex.Factorization { - using System; using System.Numerics; - using LinearAlgebra.Complex.Factorization; - using NUnit.Framework; /// /// GramSchmidt factorization tests for a user matrix. /// public class UserGramSchmidtTests { - /// - /// Constructor with null throws ArgumentNullException. - /// - public void ConstructorNullThrowsArgumentNullException() - { - Assert.Throws(() => new UserGramSchmidt(null)); - } - /// /// Constructor with wide matrix throws ArgumentException. /// [Test] public void ConstructorWideMatrixThrowsInvalidMatrixOperationException() { - Assert.Throws(() => new UserGramSchmidt(new UserDefinedMatrix(3, 4))); + Assert.Throws(() => UserGramSchmidt.Create(new UserDefinedMatrix(3, 4))); } /// diff --git a/src/UnitTests/LinearAlgebraTests/Complex32/Factorization/GramSchmidtTests.cs b/src/UnitTests/LinearAlgebraTests/Complex32/Factorization/GramSchmidtTests.cs index 0eb3cc08..5f2ba889 100644 --- a/src/UnitTests/LinearAlgebraTests/Complex32/Factorization/GramSchmidtTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Complex32/Factorization/GramSchmidtTests.cs @@ -24,10 +24,10 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Complex32; using MathNet.Numerics.LinearAlgebra.Complex32.Factorization; using NUnit.Framework; -using System; namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization { @@ -38,22 +38,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization /// public class GramSchmidtTests { - /// - /// Constructor with null throws ArgumentNullException. - /// - [Test] - public void ConstructorNullThrowsArgumentNullException() - { - Assert.Throws(() => new DenseGramSchmidt(null)); - } - /// /// Constructor with wide matrix throws ArgumentException. /// [Test] public void ConstructorWideMatrixThrowsInvalidMatrixOperationException() { - Assert.Throws(() => new DenseGramSchmidt(new DenseMatrix(3, 4))); + Assert.Throws(() => DenseGramSchmidt.Create(new DenseMatrix(3, 4))); } /// diff --git a/src/UnitTests/LinearAlgebraTests/Complex32/Factorization/UserGramSchmidtTests.cs b/src/UnitTests/LinearAlgebraTests/Complex32/Factorization/UserGramSchmidtTests.cs index 363339b1..fd6f7be2 100644 --- a/src/UnitTests/LinearAlgebraTests/Complex32/Factorization/UserGramSchmidtTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Complex32/Factorization/UserGramSchmidtTests.cs @@ -24,33 +24,26 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; +using MathNet.Numerics.LinearAlgebra.Complex32.Factorization; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32.Factorization { - using System; - using LinearAlgebra.Complex32.Factorization; - using NUnit.Framework; - using Complex32 = Numerics.Complex32; + using Numerics; /// /// GramSchmidt factorization tests for a user matrix. /// public class UserGramSchmidtTests { - /// - /// Constructor with null throws ArgumentNullException. - /// - public void ConstructorNullThrowsArgumentNullException() - { - Assert.Throws(() => new UserGramSchmidt(null)); - } - /// /// Constructor with wide matrix throws ArgumentException. /// [Test] public void ConstructorWideMatrixThrowsInvalidMatrixOperationException() { - Assert.Throws(() => new UserGramSchmidt(new UserDefinedMatrix(3, 4))); + Assert.Throws(() => UserGramSchmidt.Create(new UserDefinedMatrix(3, 4))); } /// diff --git a/src/UnitTests/LinearAlgebraTests/Double/Factorization/GramSchmidtTests.cs b/src/UnitTests/LinearAlgebraTests/Double/Factorization/GramSchmidtTests.cs index 881371fc..743ab268 100644 --- a/src/UnitTests/LinearAlgebraTests/Double/Factorization/GramSchmidtTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Double/Factorization/GramSchmidtTests.cs @@ -24,10 +24,10 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Double; using MathNet.Numerics.LinearAlgebra.Double.Factorization; using NUnit.Framework; -using System; namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization { @@ -36,22 +36,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization /// public class GramSchmidtTests { - /// - /// Constructor with null throws ArgumentNullException. - /// - [Test] - public void ConstructorNullThrowsArgumentNullException() - { - Assert.Throws(() => new DenseGramSchmidt(null)); - } - /// /// Constructor with wide matrix throws ArgumentException. /// [Test] public void ConstructorWideMatrixThrowsInvalidMatrixOperationException() { - Assert.Throws(() => new DenseGramSchmidt(new DenseMatrix(3, 4))); + Assert.Throws(() => DenseGramSchmidt.Create(new DenseMatrix(3, 4))); } /// diff --git a/src/UnitTests/LinearAlgebraTests/Double/Factorization/UserGramSchmidtTests.cs b/src/UnitTests/LinearAlgebraTests/Double/Factorization/UserGramSchmidtTests.cs index 2b9c1859..431a29c4 100644 --- a/src/UnitTests/LinearAlgebraTests/Double/Factorization/UserGramSchmidtTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Double/Factorization/UserGramSchmidtTests.cs @@ -24,32 +24,24 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; +using MathNet.Numerics.LinearAlgebra.Double.Factorization; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double.Factorization { - using System; - using LinearAlgebra.Double.Factorization; - using NUnit.Framework; - /// /// GramSchmidt factorization tests for a user matrix. /// public class UserGramSchmidtTests { - /// - /// Constructor with null throws ArgumentNullException. - /// - public void ConstructorNullThrowsArgumentNullException() - { - Assert.Throws(() => new UserGramSchmidt(null)); - } - /// /// Constructor with wide matrix throws ArgumentException. /// [Test] public void ConstructorWideMatrixThrowsInvalidMatrixOperationException() { - Assert.Throws(() => new UserGramSchmidt(new UserDefinedMatrix(3, 4))); + Assert.Throws(() => UserGramSchmidt.Create(new UserDefinedMatrix(3, 4))); } /// diff --git a/src/UnitTests/LinearAlgebraTests/Single/Factorization/GramSchmidtTests.cs b/src/UnitTests/LinearAlgebraTests/Single/Factorization/GramSchmidtTests.cs index f987eaed..413c8493 100644 --- a/src/UnitTests/LinearAlgebraTests/Single/Factorization/GramSchmidtTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Single/Factorization/GramSchmidtTests.cs @@ -24,10 +24,10 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; using MathNet.Numerics.LinearAlgebra.Single; using MathNet.Numerics.LinearAlgebra.Single.Factorization; using NUnit.Framework; -using System; namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization { @@ -36,22 +36,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization /// public class GramSchmidtTests { - /// - /// Constructor with null throws ArgumentNullException. - /// - [Test] - public void ConstructorNullThrowsArgumentNullException() - { - Assert.Throws(() => new DenseGramSchmidt(null)); - } - /// /// Constructor with wide matrix throws ArgumentException. /// [Test] public void ConstructorWideMatrixThrowsInvalidMatrixOperationException() { - Assert.Throws(() => new DenseGramSchmidt(new DenseMatrix(3, 4))); + Assert.Throws(() => DenseGramSchmidt.Create(new DenseMatrix(3, 4))); } /// diff --git a/src/UnitTests/LinearAlgebraTests/Single/Factorization/UserGramSchmidtTests.cs b/src/UnitTests/LinearAlgebraTests/Single/Factorization/UserGramSchmidtTests.cs index 36a54e31..331acb85 100644 --- a/src/UnitTests/LinearAlgebraTests/Single/Factorization/UserGramSchmidtTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Single/Factorization/UserGramSchmidtTests.cs @@ -24,32 +24,24 @@ // OTHER DEALINGS IN THE SOFTWARE. // +using System; +using MathNet.Numerics.LinearAlgebra.Single.Factorization; +using NUnit.Framework; + namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single.Factorization { - using System; - using LinearAlgebra.Single.Factorization; - using NUnit.Framework; - /// /// GramSchmidt factorization tests for a user matrix. /// public class UserGramSchmidtTests { - /// - /// Constructor with null throws ArgumentNullException. - /// - public void ConstructorNullThrowsArgumentNullException() - { - Assert.Throws(() => new UserGramSchmidt(null)); - } - /// /// Constructor with wide matrix throws ArgumentException. /// [Test] public void ConstructorWideMatrixThrowsInvalidMatrixOperationException() { - Assert.Throws(() => new UserGramSchmidt(new UserDefinedMatrix(3, 4))); + Assert.Throws(() => UserGramSchmidt.Create(new UserDefinedMatrix(3, 4))); } ///