Browse Source

LA: Simplify Cholesky decomposition architecture

optimization-1
Christoph Ruegg 13 years ago
parent
commit
eed657a63d
  1. 2
      src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs
  2. 14
      src/Numerics/LinearAlgebra/Complex/Factorization/Cholesky.cs
  3. 49
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseCholesky.cs
  4. 88
      src/Numerics/LinearAlgebra/Complex/Factorization/UserCholesky.cs
  5. 2
      src/Numerics/LinearAlgebra/Complex/Matrix.cs
  6. 2
      src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs
  7. 11
      src/Numerics/LinearAlgebra/Complex32/Factorization/Cholesky.cs
  8. 53
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseCholesky.cs
  9. 89
      src/Numerics/LinearAlgebra/Complex32/Factorization/UserCholesky.cs
  10. 2
      src/Numerics/LinearAlgebra/Complex32/Matrix.cs
  11. 2
      src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
  12. 11
      src/Numerics/LinearAlgebra/Double/Factorization/Cholesky.cs
  13. 54
      src/Numerics/LinearAlgebra/Double/Factorization/DenseCholesky.cs
  14. 89
      src/Numerics/LinearAlgebra/Double/Factorization/UserCholesky.cs
  15. 2
      src/Numerics/LinearAlgebra/Double/Matrix.cs
  16. 23
      src/Numerics/LinearAlgebra/Factorization/Cholesky.cs
  17. 2
      src/Numerics/LinearAlgebra/Single/DenseMatrix.cs
  18. 11
      src/Numerics/LinearAlgebra/Single/Factorization/Cholesky.cs
  19. 54
      src/Numerics/LinearAlgebra/Single/Factorization/DenseCholesky.cs
  20. 91
      src/Numerics/LinearAlgebra/Single/Factorization/UserCholesky.cs
  21. 2
      src/Numerics/LinearAlgebra/Single/Matrix.cs

2
src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs

@ -1011,7 +1011,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override Cholesky<Complex> Cholesky()
{
return new DenseCholesky(this);
return DenseCholesky.Create(this);
}
public override LU<Complex> LU()

14
src/Numerics/LinearAlgebra/Complex/Factorization/Cholesky.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
@ -32,10 +32,11 @@ using MathNet.Numerics.LinearAlgebra.Factorization;
namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
#if NOSYSNUMERICS
#if NOSYSNUMERICS
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#endif
/// <summary>
@ -49,6 +50,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// </remarks>
public abstract class Cholesky : Cholesky<Complex>
{
protected Cholesky(Matrix<Complex> factor)
: base(factor)
{
}
/// <summary>
/// Gets the determinant of the matrix for which the Cholesky matrix was computed.
/// </summary>
@ -60,7 +66,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
for (var j = 0; j < Factor.RowCount; j++)
{
var d = Factor.At(j, j);
det *= d * d;
det *= d*d;
}
return det;
@ -77,7 +83,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var det = Complex.Zero;
for (var j = 0; j < Factor.RowCount; j++)
{
det += 2.0 * Factor.At(j, j).Ln();
det += 2.0*Factor.At(j, j).Ln();
}
return det;

49
src/Numerics/LinearAlgebra/Complex/Factorization/DenseCholesky.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
@ -38,6 +38,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
using Numerics;
#else
using System.Numerics;
#endif
/// <summary>
@ -49,7 +50,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// The computation of the Cholesky factorization is done at construction time. If the matrix is not symmetric
/// or positive definite, the constructor will throw an exception.
/// </remarks>
public class DenseCholesky : Cholesky
public sealed class DenseCholesky : Cholesky
{
/// <summary>
/// Initializes a new instance of the <see cref="DenseCholesky"/> class. This object will compute the
@ -59,22 +60,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</exception>
public DenseCholesky(DenseMatrix matrix)
public static DenseCholesky Create(DenseMatrix matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount != matrix.ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSquare);
}
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
var factor = (DenseMatrix)matrix.Clone();
var factor = (DenseMatrix) matrix.Clone();
Control.LinearAlgebraProvider.CholeskyFactor(factor.Values, factor.RowCount);
Factor = factor;
return new DenseCholesky(factor);
}
DenseCholesky(Matrix<Complex> factor)
: base(factor)
{
}
/// <summary>
@ -84,18 +85,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<Complex> input, Matrix<Complex> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (result.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -127,7 +116,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor;
var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, dresult.ColumnCount);
}
@ -138,18 +127,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<Complex> input, Vector<Complex> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (input.Count != result.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -176,7 +153,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor;
var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, 1);
}
}

88
src/Numerics/LinearAlgebra/Complex/Factorization/UserCholesky.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
@ -39,6 +39,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
using Numerics;
#else
using System.Numerics;
#endif
/// <summary>
@ -50,7 +51,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// The computation of the Cholesky factorization is done at construction time. If the matrix is not symmetric
/// or positive definite, the constructor will throw an exception.
/// </remarks>
public class UserCholesky : Cholesky
public sealed class UserCholesky : Cholesky
{
/// <summary>
/// Initializes a new instance of the <see cref="UserCholesky"/> class. This object will compute the
@ -60,55 +61,57 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</exception>
public UserCholesky(Matrix<Complex> matrix)
public static UserCholesky Create(Matrix<Complex> matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount != matrix.ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSquare);
}
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
Factor = matrix.Clone();
var tmpColumn = new Complex[Factor.RowCount];
var factor = matrix.Clone();
var tmpColumn = new Complex[factor.RowCount];
// Main loop - along the diagonal
for (var ij = 0; ij < Factor.RowCount; ij++)
for (var ij = 0; ij < factor.RowCount; ij++)
{
// "Pivot" element
var tmpVal = Factor.At(ij, ij);
var tmpVal = factor.At(ij, ij);
if (tmpVal.Real > 0.0)
{
tmpVal = tmpVal.SquareRoot();
Factor.At(ij, ij, tmpVal);
factor.At(ij, ij, tmpVal);
tmpColumn[ij] = tmpVal;
// Calculate multipliers and copy to local column
// Current column, below the diagonal
for (var i = ij + 1; i < Factor.RowCount; i++)
for (var i = ij + 1; i < factor.RowCount; i++)
{
Factor.At(i, ij, Factor.At(i, ij) / tmpVal);
tmpColumn[i] = Factor.At(i, ij);
factor.At(i, ij, factor.At(i, ij)/tmpVal);
tmpColumn[i] = factor.At(i, ij);
}
// Remaining columns, below the diagonal
DoCholeskyStep(Factor, Factor.RowCount, ij + 1, Factor.RowCount, tmpColumn, Control.NumberOfParallelWorkerThreads);
DoCholeskyStep(factor, factor.RowCount, ij + 1, factor.RowCount, tmpColumn, Control.NumberOfParallelWorkerThreads);
}
else
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
}
for (var i = ij + 1; i < Factor.RowCount; i++)
for (var i = ij + 1; i < factor.RowCount; i++)
{
Factor.At(ij, i, Complex.Zero);
factor.At(ij, i, Complex.Zero);
}
}
return new UserCholesky(factor);
}
UserCholesky(Matrix<Complex> factor)
: base(factor)
{
}
/// <summary>
@ -120,14 +123,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <param name="colLimit">Total columns</param>
/// <param name="multipliers">Multipliers calculated previously</param>
/// <param name="availableCores">Number of available processors</param>
private static void DoCholeskyStep(Matrix<Complex> data, int rowDim, int firstCol, int colLimit, Complex[] multipliers, int availableCores)
static void DoCholeskyStep(Matrix<Complex> data, int rowDim, int firstCol, int colLimit, Complex[] multipliers, int availableCores)
{
var tmpColCount = colLimit - firstCol;
if ((availableCores > 1) && (tmpColCount > 200))
{
var tmpSplit = firstCol + (tmpColCount / 3);
var tmpCores = availableCores / 2;
var tmpSplit = firstCol + (tmpColCount/3);
var tmpCores = availableCores/2;
CommonParallel.Invoke(
() => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores),
@ -140,7 +143,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var tmpVal = multipliers[j];
for (var i = j; i < rowDim; i++)
{
data.At(i, j, data.At(i, j) - (multipliers[i] * tmpVal.Conjugate()));
data.At(i, j, data.At(i, j) - (multipliers[i]*tmpVal.Conjugate()));
}
}
}
@ -153,17 +156,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<Complex> input, Matrix<Complex> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (result.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -191,10 +183,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
sum = result.At(i, c);
for (var k = i - 1; k >= 0; k--)
{
sum -= Factor.At(i, k) * result.At(k, c);
sum -= Factor.At(i, k)*result.At(k, c);
}
result.At(i, c, sum / Factor.At(i, i));
result.At(i, c, sum/Factor.At(i, i));
}
// Solve L'*X = Y;
@ -203,10 +195,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
sum = result.At(i, c);
for (var k = i + 1; k < order; k++)
{
sum -= Factor.At(k, i).Conjugate() * result.At(k, c);
sum -= Factor.At(k, i).Conjugate()*result.At(k, c);
}
result.At(i, c, sum / Factor.At(i, i));
result.At(i, c, sum/Factor.At(i, i));
}
}
}
@ -218,18 +210,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<Complex> input, Vector<Complex> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (input.Count != result.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -250,10 +230,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
sum = result[i];
for (var k = i - 1; k >= 0; k--)
{
sum -= Factor.At(i, k) * result[k];
sum -= Factor.At(i, k)*result[k];
}
result[i] = sum / Factor.At(i, i);
result[i] = sum/Factor.At(i, i);
}
// Solve L'*X = Y;
@ -262,10 +242,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
sum = result[i];
for (var k = i + 1; k < order; k++)
{
sum -= Factor.At(k, i).Conjugate() * result[k];
sum -= Factor.At(k, i).Conjugate()*result[k];
}
result[i] = sum / Factor.At(i, i);
result[i] = sum/Factor.At(i, i);
}
}
}

2
src/Numerics/LinearAlgebra/Complex/Matrix.cs

@ -460,7 +460,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override Cholesky<Complex> Cholesky()
{
return new UserCholesky(this);
return UserCholesky.Create(this);
}
public override LU<Complex> LU()

2
src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs

@ -1006,7 +1006,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override Cholesky<Complex32> Cholesky()
{
return new DenseCholesky(this);
return DenseCholesky.Create(this);
}
public override LU<Complex32> LU()

11
src/Numerics/LinearAlgebra/Complex32/Factorization/Cholesky.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
@ -45,6 +45,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// </remarks>
public abstract class Cholesky : Cholesky<Complex32>
{
protected Cholesky(Matrix<Complex32> factor)
: base(factor)
{
}
/// <summary>
/// Gets the determinant of the matrix for which the Cholesky matrix was computed.
/// </summary>
@ -56,7 +61,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
for (var j = 0; j < Factor.RowCount; j++)
{
var d = Factor.At(j, j);
det *= d * d;
det *= d*d;
}
return det;
@ -73,7 +78,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var det = Complex32.Zero;
for (var j = 0; j < Factor.RowCount; j++)
{
det += 2.0f * Factor.At(j, j).NaturalLogarithm();
det += 2.0f*Factor.At(j, j).NaturalLogarithm();
}
return det;

53
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseCholesky.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,11 +28,12 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
using System;
using Numerics;
using Properties;
/// <summary>
/// <para>A class which encapsulates the functionality of a Cholesky factorization for dense matrices.</para>
@ -43,7 +44,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// The computation of the Cholesky factorization is done at construction time. If the matrix is not symmetric
/// or positive definite, the constructor will throw an exception.
/// </remarks>
public class DenseCholesky : Cholesky
public sealed class DenseCholesky : Cholesky
{
/// <summary>
/// Initializes a new instance of the <see cref="DenseCholesky"/> class. This object will compute the
@ -53,22 +54,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</exception>
public DenseCholesky(DenseMatrix matrix)
public static DenseCholesky Create(DenseMatrix matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount != matrix.ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSquare);
}
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
var factor = (DenseMatrix)matrix.Clone();
var factor = (DenseMatrix) matrix.Clone();
Control.LinearAlgebraProvider.CholeskyFactor(factor.Values, factor.RowCount);
Factor = factor;
return new DenseCholesky(factor);
}
DenseCholesky(Matrix<Complex32> factor)
: base(factor)
{
}
/// <summary>
@ -78,18 +79,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<Complex32> input, Matrix<Complex32> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (result.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -121,7 +110,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor;
var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, dresult.ColumnCount);
}
@ -132,18 +121,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<Complex32> input, Vector<Complex32> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (input.Count != result.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -170,7 +147,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor;
var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, 1);
}
}

89
src/Numerics/LinearAlgebra/Complex32/Factorization/UserCholesky.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,9 +28,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.Properties;
using MathNet.Numerics.Threading;
using System;
namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
@ -45,7 +45,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// The computation of the Cholesky factorization is done at construction time. If the matrix is not symmetric
/// or positive definite, the constructor will throw an exception.
/// </remarks>
public class UserCholesky : Cholesky
public sealed class UserCholesky : Cholesky
{
/// <summary>
/// Initializes a new instance of the <see cref="UserCholesky"/> class. This object will compute the
@ -55,55 +55,57 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</exception>
public UserCholesky(Matrix<Complex32> matrix)
public static UserCholesky Create(Matrix<Complex32> matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount != matrix.ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSquare);
}
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
Factor = matrix.Clone();
var tmpColumn = new Complex32[Factor.RowCount];
var factor = matrix.Clone();
var tmpColumn = new Complex32[factor.RowCount];
// Main loop - along the diagonal
for (var ij = 0; ij < Factor.RowCount; ij++)
for (var ij = 0; ij < factor.RowCount; ij++)
{
// "Pivot" element
var tmpVal = Factor.At(ij, ij);
var tmpVal = factor.At(ij, ij);
if (tmpVal.Real > 0.0)
{
tmpVal = tmpVal.SquareRoot();
Factor.At(ij, ij, tmpVal);
factor.At(ij, ij, tmpVal);
tmpColumn[ij] = tmpVal;
// Calculate multipliers and copy to local column
// Current column, below the diagonal
for (var i = ij + 1; i < Factor.RowCount; i++)
for (var i = ij + 1; i < factor.RowCount; i++)
{
Factor.At(i, ij, Factor.At(i, ij) / tmpVal);
tmpColumn[i] = Factor.At(i, ij);
factor.At(i, ij, factor.At(i, ij)/tmpVal);
tmpColumn[i] = factor.At(i, ij);
}
// Remaining columns, below the diagonal
DoCholeskyStep(Factor, Factor.RowCount, ij + 1, Factor.RowCount, tmpColumn, Control.NumberOfParallelWorkerThreads);
DoCholeskyStep(factor, factor.RowCount, ij + 1, factor.RowCount, tmpColumn, Control.NumberOfParallelWorkerThreads);
}
else
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
}
for (var i = ij + 1; i < Factor.RowCount; i++)
for (var i = ij + 1; i < factor.RowCount; i++)
{
Factor.At(ij, i, Complex32.Zero);
factor.At(ij, i, Complex32.Zero);
}
}
return new UserCholesky(factor);
}
UserCholesky(Matrix<Complex32> factor)
: base(factor)
{
}
/// <summary>
@ -115,14 +117,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <param name="colLimit">Total columns</param>
/// <param name="multipliers">Multipliers calculated previously</param>
/// <param name="availableCores">Number of available processors</param>
private static void DoCholeskyStep(Matrix<Complex32> data, int rowDim, int firstCol, int colLimit, Complex32[] multipliers, int availableCores)
static void DoCholeskyStep(Matrix<Complex32> data, int rowDim, int firstCol, int colLimit, Complex32[] multipliers, int availableCores)
{
var tmpColCount = colLimit - firstCol;
if ((availableCores > 1) && (tmpColCount > 200))
{
var tmpSplit = firstCol + (tmpColCount / 3);
var tmpCores = availableCores / 2;
var tmpSplit = firstCol + (tmpColCount/3);
var tmpCores = availableCores/2;
CommonParallel.Invoke(
() => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores),
@ -135,7 +137,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var tmpVal = multipliers[j];
for (var i = j; i < rowDim; i++)
{
data.At(i, j, data.At(i, j) - (multipliers[i] * tmpVal.Conjugate()));
data.At(i, j, data.At(i, j) - (multipliers[i]*tmpVal.Conjugate()));
}
}
}
@ -148,17 +150,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<Complex32> input, Matrix<Complex32> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (result.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -186,10 +177,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
sum = result.At(i, c);
for (var k = i - 1; k >= 0; k--)
{
sum -= Factor.At(i, k) * result.At(k, c);
sum -= Factor.At(i, k)*result.At(k, c);
}
result.At(i, c, sum / Factor.At(i, i));
result.At(i, c, sum/Factor.At(i, i));
}
// Solve L'*X = Y;
@ -198,10 +189,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
sum = result.At(i, c);
for (var k = i + 1; k < order; k++)
{
sum -= Factor.At(k, i).Conjugate() * result.At(k, c);
sum -= Factor.At(k, i).Conjugate()*result.At(k, c);
}
result.At(i, c, sum / Factor.At(i, i));
result.At(i, c, sum/Factor.At(i, i));
}
}
}
@ -213,18 +204,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<Complex32> input, Vector<Complex32> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (input.Count != result.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -245,10 +224,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
sum = result[i];
for (var k = i - 1; k >= 0; k--)
{
sum -= Factor.At(i, k) * result[k];
sum -= Factor.At(i, k)*result[k];
}
result[i] = sum / Factor.At(i, i);
result[i] = sum/Factor.At(i, i);
}
// Solve L'*X = Y;
@ -257,10 +236,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
sum = result[i];
for (var k = i + 1; k < order; k++)
{
sum -= Factor.At(k, i).Conjugate() * result[k];
sum -= Factor.At(k, i).Conjugate()*result[k];
}
result[i] = sum / Factor.At(i, i);
result[i] = sum/Factor.At(i, i);
}
}
}

2
src/Numerics/LinearAlgebra/Complex32/Matrix.cs

@ -455,7 +455,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override Cholesky<Complex32> Cholesky()
{
return new UserCholesky(this);
return UserCholesky.Create(this);
}
public override LU<Complex32> LU()

2
src/Numerics/LinearAlgebra/Double/DenseMatrix.cs

@ -1037,7 +1037,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override Cholesky<double> Cholesky()
{
return new DenseCholesky(this);
return DenseCholesky.Create(this);
}
public override LU<double> LU()

11
src/Numerics/LinearAlgebra/Double/Factorization/Cholesky.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
@ -45,6 +45,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// </remarks>
public abstract class Cholesky : Cholesky<double>
{
protected Cholesky(Matrix<double> factor)
: base(factor)
{
}
/// <summary>
/// Gets the determinant of the matrix for which the Cholesky matrix was computed.
/// </summary>
@ -56,7 +61,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
for (var j = 0; j < Factor.RowCount; j++)
{
var d = Factor.At(j, j);
det *= d * d;
det *= d*d;
}
return det;
@ -73,7 +78,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
var det = 0.0;
for (var j = 0; j < Factor.RowCount; j++)
{
det += 2 * Math.Log(Factor.At(j, j));
det += 2*Math.Log(Factor.At(j, j));
}
return det;

54
src/Numerics/LinearAlgebra/Double/Factorization/DenseCholesky.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.
// </copyright>
using MathNet.Numerics.Properties;
using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
@ -42,7 +42,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// The computation of the Cholesky factorization is done at construction time. If the matrix is not symmetric
/// or positive definite, the constructor will throw an exception.
/// </remarks>
public class DenseCholesky : Cholesky
public sealed class DenseCholesky : Cholesky
{
/// <summary>
/// Initializes a new instance of the <see cref="DenseCholesky"/> class. This object will compute the
@ -52,22 +52,22 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</exception>
public DenseCholesky(DenseMatrix matrix)
public static DenseCholesky Create(DenseMatrix matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount != matrix.ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSquare);
}
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
var factor = (DenseMatrix)matrix.Clone();
var factor = (DenseMatrix) matrix.Clone();
Control.LinearAlgebraProvider.CholeskyFactor(factor.Values, factor.RowCount);
Factor = factor;
return new DenseCholesky(factor);
}
DenseCholesky(Matrix<double> factor)
: base(factor)
{
}
/// <summary>
@ -77,18 +77,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<double> input, Matrix<double> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (result.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -117,10 +105,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
}
// Copy the contents of input to result.
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length * Constants.SizeOfDouble);
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length*Constants.SizeOfDouble);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor;
var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, dresult.ColumnCount);
}
@ -131,18 +119,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<double> input, Vector<double> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (input.Count != result.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -166,10 +142,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
}
// Copy the contents of input to result.
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length * Constants.SizeOfDouble);
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length*Constants.SizeOfDouble);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor;
var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, 1);
}
}

89
src/Numerics/LinearAlgebra/Double/Factorization/UserCholesky.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,9 +28,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.Properties;
using MathNet.Numerics.Threading;
using System;
namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
{
@ -43,7 +43,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// The computation of the Cholesky factorization is done at construction time. If the matrix is not symmetric
/// or positive definite, the constructor will throw an exception.
/// </remarks>
public class UserCholesky : Cholesky
public sealed class UserCholesky : Cholesky
{
/// <summary>
/// Initializes a new instance of the <see cref="UserCholesky"/> class. This object will compute the
@ -53,55 +53,57 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</exception>
public UserCholesky(Matrix<double> matrix)
public static UserCholesky Create(Matrix<double> matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount != matrix.ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSquare);
}
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
Factor = matrix.Clone();
var tmpColumn = new double[Factor.RowCount];
var factor = matrix.Clone();
var tmpColumn = new double[factor.RowCount];
// Main loop - along the diagonal
for (var ij = 0; ij < Factor.RowCount; ij++)
for (var ij = 0; ij < factor.RowCount; ij++)
{
// "Pivot" element
var tmpVal = Factor.At(ij, ij);
var tmpVal = factor.At(ij, ij);
if (tmpVal > 0.0)
{
tmpVal = Math.Sqrt(tmpVal);
Factor.At(ij, ij, tmpVal);
factor.At(ij, ij, tmpVal);
tmpColumn[ij] = tmpVal;
// Calculate multipliers and copy to local column
// Current column, below the diagonal
for (var i = ij + 1; i < Factor.RowCount; i++)
for (var i = ij + 1; i < factor.RowCount; i++)
{
Factor.At(i, ij, Factor.At(i, ij) / tmpVal);
tmpColumn[i] = Factor.At(i, ij);
factor.At(i, ij, factor.At(i, ij)/tmpVal);
tmpColumn[i] = factor.At(i, ij);
}
// Remaining columns, below the diagonal
DoCholeskyStep(Factor, Factor.RowCount, ij + 1, Factor.RowCount, tmpColumn, Control.NumberOfParallelWorkerThreads);
DoCholeskyStep(factor, factor.RowCount, ij + 1, factor.RowCount, tmpColumn, Control.NumberOfParallelWorkerThreads);
}
else
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
}
for (var i = ij + 1; i < Factor.RowCount; i++)
for (var i = ij + 1; i < factor.RowCount; i++)
{
Factor.At(ij, i, 0.0);
factor.At(ij, i, 0.0);
}
}
return new UserCholesky(factor);
}
UserCholesky(Matrix<double> factor)
: base(factor)
{
}
/// <summary>
@ -113,14 +115,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <param name="colLimit">Total columns</param>
/// <param name="multipliers">Multipliers calculated previously</param>
/// <param name="availableCores">Number of available processors</param>
private static void DoCholeskyStep(Matrix<double> data, int rowDim, int firstCol, int colLimit, double[] multipliers, int availableCores)
static void DoCholeskyStep(Matrix<double> data, int rowDim, int firstCol, int colLimit, double[] multipliers, int availableCores)
{
var tmpColCount = colLimit - firstCol;
if ((availableCores > 1) && (tmpColCount > 200))
{
var tmpSplit = firstCol + (tmpColCount / 3);
var tmpCores = availableCores / 2;
var tmpSplit = firstCol + (tmpColCount/3);
var tmpCores = availableCores/2;
CommonParallel.Invoke(
() => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores),
@ -133,7 +135,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
var tmpVal = multipliers[j];
for (var i = j; i < rowDim; i++)
{
data.At(i, j, data.At(i, j) - (multipliers[i] * tmpVal));
data.At(i, j, data.At(i, j) - (multipliers[i]*tmpVal));
}
}
}
@ -146,17 +148,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<double> input, Matrix<double> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (result.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -184,10 +175,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
sum = result.At(i, c);
for (var k = i - 1; k >= 0; k--)
{
sum -= Factor.At(i, k) * result.At(k, c);
sum -= Factor.At(i, k)*result.At(k, c);
}
result.At(i, c, sum / Factor.At(i, i));
result.At(i, c, sum/Factor.At(i, i));
}
// Solve L'*X = Y;
@ -196,10 +187,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
sum = result.At(i, c);
for (var k = i + 1; k < order; k++)
{
sum -= Factor.At(k, i) * result.At(k, c);
sum -= Factor.At(k, i)*result.At(k, c);
}
result.At(i, c, sum / Factor.At(i, i));
result.At(i, c, sum/Factor.At(i, i));
}
}
}
@ -211,18 +202,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<double> input, Vector<double> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (input.Count != result.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -243,10 +222,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
sum = result[i];
for (var k = i - 1; k >= 0; k--)
{
sum -= Factor.At(i, k) * result[k];
sum -= Factor.At(i, k)*result[k];
}
result[i] = sum / Factor.At(i, i);
result[i] = sum/Factor.At(i, i);
}
// Solve L'*X = Y;
@ -255,10 +234,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
sum = result[i];
for (var k = i + 1; k < order; k++)
{
sum -= Factor.At(k, i) * result[k];
sum -= Factor.At(k, i)*result[k];
}
result[i] = sum / Factor.At(i, i);
result[i] = sum/Factor.At(i, i);
}
}
}

2
src/Numerics/LinearAlgebra/Double/Matrix.cs

@ -461,7 +461,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override Cholesky<double> Cholesky()
{
return new UserCholesky(this);
return UserCholesky.Create(this);
}
public override LU<double> LU()

23
src/Numerics/LinearAlgebra/Factorization/Cholesky.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
@ -43,12 +43,17 @@ namespace MathNet.Numerics.LinearAlgebra.Factorization
/// </remarks>
/// <typeparam name="T">Supported data types are double, single, <see cref="Complex"/>, and <see cref="Complex32"/>.</typeparam>
public abstract class Cholesky<T> : ISolver<T>
where T : struct, IEquatable<T>, IFormattable
where T : struct, IEquatable<T>, IFormattable
{
protected Cholesky(Matrix<T> factor)
{
Factor = factor;
}
/// <summary>
/// Gets the lower triangular form of the Cholesky matrix.
/// </summary>
public Matrix<T> Factor { get; protected set; }
public Matrix<T> Factor { get; private set; }
/// <summary>
/// Gets the determinant of the matrix for which the Cholesky matrix was computed.
@ -67,12 +72,6 @@ namespace MathNet.Numerics.LinearAlgebra.Factorization
/// <returns>The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</returns>
public virtual Matrix<T> Solve(Matrix<T> input)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
var x = input.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(input, x);
return x;
@ -92,12 +91,6 @@ namespace MathNet.Numerics.LinearAlgebra.Factorization
/// <returns>The left hand side <see cref="Vector{T}"/>, <b>x</b>.</returns>
public virtual Vector<T> Solve(Vector<T> input)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
var x = input.CreateVector(input.Count);
Solve(input, x);
return x;

2
src/Numerics/LinearAlgebra/Single/DenseMatrix.cs

@ -1037,7 +1037,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override Cholesky<float> Cholesky()
{
return new DenseCholesky(this);
return DenseCholesky.Create(this);
}
public override LU<float> LU()

11
src/Numerics/LinearAlgebra/Single/Factorization/Cholesky.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
@ -45,6 +45,11 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// </remarks>
public abstract class Cholesky : Cholesky<float>
{
protected Cholesky(Matrix<float> factor)
: base(factor)
{
}
/// <summary>
/// Gets the determinant of the matrix for which the Cholesky matrix was computed.
/// </summary>
@ -56,7 +61,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
for (var j = 0; j < Factor.RowCount; j++)
{
var d = Factor.At(j, j);
det *= d * d;
det *= d*d;
}
return det;
@ -73,7 +78,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
var det = 0.0f;
for (var j = 0; j < Factor.RowCount; j++)
{
det += 2.0f * Convert.ToSingle(Math.Log(Factor.At(j, j)));
det += 2.0f*Convert.ToSingle(Math.Log(Factor.At(j, j)));
}
return det;

54
src/Numerics/LinearAlgebra/Single/Factorization/DenseCholesky.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.
// </copyright>
using MathNet.Numerics.Properties;
using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
{
@ -42,7 +42,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// The computation of the Cholesky factorization is done at construction time. If the matrix is not symmetric
/// or positive definite, the constructor will throw an exception.
/// </remarks>
public class DenseCholesky : Cholesky
public sealed class DenseCholesky : Cholesky
{
/// <summary>
/// Initializes a new instance of the <see cref="DenseCholesky"/> class. This object will compute the
@ -52,22 +52,22 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</exception>
public DenseCholesky(DenseMatrix matrix)
public static DenseCholesky Create(DenseMatrix matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount != matrix.ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSquare);
}
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
var factor = (DenseMatrix)matrix.Clone();
var factor = (DenseMatrix) matrix.Clone();
Control.LinearAlgebraProvider.CholeskyFactor(factor.Values, factor.RowCount);
Factor = factor;
return new DenseCholesky(factor);
}
DenseCholesky(Matrix<float> factor)
: base(factor)
{
}
/// <summary>
@ -77,18 +77,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<float> input, Matrix<float> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (result.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -117,10 +105,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
}
// Copy the contents of input to result.
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length * Constants.SizeOfFloat);
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length*Constants.SizeOfFloat);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor;
var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, dresult.ColumnCount);
}
@ -131,18 +119,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<float> input, Vector<float> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (input.Count != result.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -166,10 +142,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
}
// Copy the contents of input to result.
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length * Constants.SizeOfFloat);
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length*Constants.SizeOfFloat);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor;
var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, 1);
}
}

91
src/Numerics/LinearAlgebra/Single/Factorization/UserCholesky.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,9 +28,9 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.Properties;
using MathNet.Numerics.Threading;
using System;
namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
{
@ -43,7 +43,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// The computation of the Cholesky factorization is done at construction time. If the matrix is not symmetric
/// or positive definite, the constructor will throw an exception.
/// </remarks>
public class UserCholesky : Cholesky
public sealed class UserCholesky : Cholesky
{
/// <summary>
/// Initializes a new instance of the <see cref="UserCholesky"/> class. This object will compute the
@ -53,55 +53,57 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</exception>
public UserCholesky(Matrix<float> matrix)
public static UserCholesky Create(Matrix<float> matrix)
{
if (matrix == null)
{
throw new ArgumentNullException("matrix");
}
if (matrix.RowCount != matrix.ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSquare);
}
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
Factor = matrix.Clone();
var tmpColumn = new float[Factor.RowCount];
var factor = matrix.Clone();
var tmpColumn = new float[factor.RowCount];
// Main loop - along the diagonal
for (var ij = 0; ij < Factor.RowCount; ij++)
for (var ij = 0; ij < factor.RowCount; ij++)
{
// "Pivot" element
var tmpVal = Factor.At(ij, ij);
var tmpVal = factor.At(ij, ij);
if (tmpVal > 0.0)
{
tmpVal = (float)Math.Sqrt(tmpVal);
Factor.At(ij, ij, tmpVal);
tmpVal = (float) Math.Sqrt(tmpVal);
factor.At(ij, ij, tmpVal);
tmpColumn[ij] = tmpVal;
// Calculate multipliers and copy to local column
// Current column, below the diagonal
for (var i = ij + 1; i < Factor.RowCount; i++)
for (var i = ij + 1; i < factor.RowCount; i++)
{
Factor.At(i, ij, Factor.At(i, ij) / tmpVal);
tmpColumn[i] = Factor.At(i, ij);
factor.At(i, ij, factor.At(i, ij)/tmpVal);
tmpColumn[i] = factor.At(i, ij);
}
// Remaining columns, below the diagonal
DoCholeskyStep(Factor, Factor.RowCount, ij + 1, Factor.RowCount, tmpColumn, Control.NumberOfParallelWorkerThreads);
DoCholeskyStep(factor, factor.RowCount, ij + 1, factor.RowCount, tmpColumn, Control.NumberOfParallelWorkerThreads);
}
else
{
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite);
}
for (var i = ij + 1; i < Factor.RowCount; i++)
for (var i = ij + 1; i < factor.RowCount; i++)
{
Factor.At(ij, i, 0.0f);
factor.At(ij, i, 0.0f);
}
}
return new UserCholesky(factor);
}
UserCholesky(Matrix<float> factor)
: base(factor)
{
}
/// <summary>
@ -113,14 +115,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <param name="colLimit">Total columns</param>
/// <param name="multipliers">Multipliers calculated previously</param>
/// <param name="availableCores">Number of available processors</param>
private static void DoCholeskyStep(Matrix<float> data, int rowDim, int firstCol, int colLimit, float[] multipliers, int availableCores)
static void DoCholeskyStep(Matrix<float> data, int rowDim, int firstCol, int colLimit, float[] multipliers, int availableCores)
{
var tmpColCount = colLimit - firstCol;
if ((availableCores > 1) && (tmpColCount > 200))
{
var tmpSplit = firstCol + (tmpColCount / 3);
var tmpCores = availableCores / 2;
var tmpSplit = firstCol + (tmpColCount/3);
var tmpCores = availableCores/2;
CommonParallel.Invoke(
() => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores),
@ -133,7 +135,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
var tmpVal = multipliers[j];
for (var i = j; i < rowDim; i++)
{
data.At(i, j, data.At(i, j) - (multipliers[i] * tmpVal));
data.At(i, j, data.At(i, j) - (multipliers[i]*tmpVal));
}
}
}
@ -146,17 +148,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
public override void Solve(Matrix<float> input, Matrix<float> result)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (result.RowCount != input.RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -184,10 +175,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
sum = result.At(i, c);
for (var k = i - 1; k >= 0; k--)
{
sum -= Factor.At(i, k) * result.At(k, c);
sum -= Factor.At(i, k)*result.At(k, c);
}
result.At(i, c, sum / Factor.At(i, i));
result.At(i, c, sum/Factor.At(i, i));
}
// Solve L'*X = Y;
@ -196,10 +187,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
sum = result.At(i, c);
for (var k = i + 1; k < order; k++)
{
sum -= Factor.At(k, i) * result.At(k, c);
sum -= Factor.At(k, i)*result.At(k, c);
}
result.At(i, c, sum / Factor.At(i, i));
result.At(i, c, sum/Factor.At(i, i));
}
}
}
@ -211,18 +202,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
public override void Solve(Vector<float> input, Vector<float> result)
{
// Check for proper arguments.
if (input == null)
{
throw new ArgumentNullException("input");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
// Check for proper dimensions.
if (input.Count != result.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -243,10 +222,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
sum = result[i];
for (var k = i - 1; k >= 0; k--)
{
sum -= Factor.At(i, k) * result[k];
sum -= Factor.At(i, k)*result[k];
}
result[i] = sum / Factor.At(i, i);
result[i] = sum/Factor.At(i, i);
}
// Solve L'*X = Y;
@ -255,10 +234,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
sum = result[i];
for (var k = i + 1; k < order; k++)
{
sum -= Factor.At(k, i) * result[k];
sum -= Factor.At(k, i)*result[k];
}
result[i] = sum / Factor.At(i, i);
result[i] = sum/Factor.At(i, i);
}
}
}

2
src/Numerics/LinearAlgebra/Single/Matrix.cs

@ -461,7 +461,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override Cholesky<float> Cholesky()
{
return new UserCholesky(this);
return UserCholesky.Create(this);
}
public override LU<float> LU()

Loading…
Cancel
Save