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() public override Cholesky<Complex> Cholesky()
{ {
return new DenseCholesky(this); return DenseCholesky.Create(this);
} }
public override LU<Complex> LU() public override LU<Complex> LU()

14
src/Numerics/LinearAlgebra/Complex/Factorization/Cholesky.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -32,10 +32,11 @@ using MathNet.Numerics.LinearAlgebra.Factorization;
namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{ {
#if NOSYSNUMERICS #if NOSYSNUMERICS
using Complex = Numerics.Complex; using Complex = Numerics.Complex;
#else #else
using Complex = System.Numerics.Complex; using Complex = System.Numerics.Complex;
#endif #endif
/// <summary> /// <summary>
@ -49,6 +50,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// </remarks> /// </remarks>
public abstract class Cholesky : Cholesky<Complex> public abstract class Cholesky : Cholesky<Complex>
{ {
protected Cholesky(Matrix<Complex> factor)
: base(factor)
{
}
/// <summary> /// <summary>
/// Gets the determinant of the matrix for which the Cholesky matrix was computed. /// Gets the determinant of the matrix for which the Cholesky matrix was computed.
/// </summary> /// </summary>
@ -60,7 +66,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
for (var j = 0; j < Factor.RowCount; j++) for (var j = 0; j < Factor.RowCount; j++)
{ {
var d = Factor.At(j, j); var d = Factor.At(j, j);
det *= d * d; det *= d*d;
} }
return det; return det;
@ -77,7 +83,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var det = Complex.Zero; var det = Complex.Zero;
for (var j = 0; j < Factor.RowCount; j++) 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; return det;

49
src/Numerics/LinearAlgebra/Complex/Factorization/DenseCholesky.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -38,6 +38,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
using Numerics; using Numerics;
#else #else
using System.Numerics; using System.Numerics;
#endif #endif
/// <summary> /// <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 /// 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. /// or positive definite, the constructor will throw an exception.
/// </remarks> /// </remarks>
public class DenseCholesky : Cholesky public sealed class DenseCholesky : Cholesky
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="DenseCholesky"/> class. This object will compute the /// 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="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 a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</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) if (matrix.RowCount != matrix.ColumnCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSquare); throw new ArgumentException(Resources.ArgumentMatrixSquare);
} }
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting). // 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); Control.LinearAlgebraProvider.CholeskyFactor(factor.Values, factor.RowCount);
Factor = factor; return new DenseCholesky(factor);
}
DenseCholesky(Matrix<Complex> factor)
: base(factor)
{
} }
/// <summary> /// <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> /// <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) 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) if (result.RowCount != input.RowCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension); throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -127,7 +116,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor; var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, dresult.ColumnCount); 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> /// <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) 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) if (input.Count != result.Count)
{ {
throw new ArgumentException(Resources.ArgumentVectorsSameLength); throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -176,7 +153,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor; var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, 1); 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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -39,6 +39,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
using Numerics; using Numerics;
#else #else
using System.Numerics; using System.Numerics;
#endif #endif
/// <summary> /// <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 /// 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. /// or positive definite, the constructor will throw an exception.
/// </remarks> /// </remarks>
public class UserCholesky : Cholesky public sealed class UserCholesky : Cholesky
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UserCholesky"/> class. This object will compute the /// 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="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 a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</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) if (matrix.RowCount != matrix.ColumnCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSquare); throw new ArgumentException(Resources.ArgumentMatrixSquare);
} }
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting). // Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
Factor = matrix.Clone(); var factor = matrix.Clone();
var tmpColumn = new Complex[Factor.RowCount]; var tmpColumn = new Complex[factor.RowCount];
// Main loop - along the diagonal // Main loop - along the diagonal
for (var ij = 0; ij < Factor.RowCount; ij++) for (var ij = 0; ij < factor.RowCount; ij++)
{ {
// "Pivot" element // "Pivot" element
var tmpVal = Factor.At(ij, ij); var tmpVal = factor.At(ij, ij);
if (tmpVal.Real > 0.0) if (tmpVal.Real > 0.0)
{ {
tmpVal = tmpVal.SquareRoot(); tmpVal = tmpVal.SquareRoot();
Factor.At(ij, ij, tmpVal); factor.At(ij, ij, tmpVal);
tmpColumn[ij] = tmpVal; tmpColumn[ij] = tmpVal;
// Calculate multipliers and copy to local column // Calculate multipliers and copy to local column
// Current column, below the diagonal // 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); factor.At(i, ij, factor.At(i, ij)/tmpVal);
tmpColumn[i] = Factor.At(i, ij); tmpColumn[i] = factor.At(i, ij);
} }
// Remaining columns, below the diagonal // 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 else
{ {
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite); 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> /// <summary>
@ -120,14 +123,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
/// <param name="colLimit">Total columns</param> /// <param name="colLimit">Total columns</param>
/// <param name="multipliers">Multipliers calculated previously</param> /// <param name="multipliers">Multipliers calculated previously</param>
/// <param name="availableCores">Number of available processors</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; var tmpColCount = colLimit - firstCol;
if ((availableCores > 1) && (tmpColCount > 200)) if ((availableCores > 1) && (tmpColCount > 200))
{ {
var tmpSplit = firstCol + (tmpColCount / 3); var tmpSplit = firstCol + (tmpColCount/3);
var tmpCores = availableCores / 2; var tmpCores = availableCores/2;
CommonParallel.Invoke( CommonParallel.Invoke(
() => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores), () => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores),
@ -140,7 +143,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
var tmpVal = multipliers[j]; var tmpVal = multipliers[j];
for (var i = j; i < rowDim; i++) 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> /// <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) 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) if (result.RowCount != input.RowCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension); throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -191,10 +183,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
sum = result.At(i, c); sum = result.At(i, c);
for (var k = i - 1; k >= 0; k--) 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; // Solve L'*X = Y;
@ -203,10 +195,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
sum = result.At(i, c); sum = result.At(i, c);
for (var k = i + 1; k < order; k++) 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> /// <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) 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) if (input.Count != result.Count)
{ {
throw new ArgumentException(Resources.ArgumentVectorsSameLength); throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -250,10 +230,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
sum = result[i]; sum = result[i];
for (var k = i - 1; k >= 0; k--) 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; // Solve L'*X = Y;
@ -262,10 +242,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
sum = result[i]; sum = result[i];
for (var k = i + 1; k < order; k++) 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() public override Cholesky<Complex> Cholesky()
{ {
return new UserCholesky(this); return UserCholesky.Create(this);
} }
public override LU<Complex> LU() 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() public override Cholesky<Complex32> Cholesky()
{ {
return new DenseCholesky(this); return DenseCholesky.Create(this);
} }
public override LU<Complex32> LU() public override LU<Complex32> LU()

11
src/Numerics/LinearAlgebra/Complex32/Factorization/Cholesky.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -45,6 +45,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// </remarks> /// </remarks>
public abstract class Cholesky : Cholesky<Complex32> public abstract class Cholesky : Cholesky<Complex32>
{ {
protected Cholesky(Matrix<Complex32> factor)
: base(factor)
{
}
/// <summary> /// <summary>
/// Gets the determinant of the matrix for which the Cholesky matrix was computed. /// Gets the determinant of the matrix for which the Cholesky matrix was computed.
/// </summary> /// </summary>
@ -56,7 +61,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
for (var j = 0; j < Factor.RowCount; j++) for (var j = 0; j < Factor.RowCount; j++)
{ {
var d = Factor.At(j, j); var d = Factor.At(j, j);
det *= d * d; det *= d*d;
} }
return det; return det;
@ -73,7 +78,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var det = Complex32.Zero; var det = Complex32.Zero;
for (var j = 0; j < Factor.RowCount; j++) 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; return det;

53
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseCholesky.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,11 +28,12 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{ {
using System;
using Numerics; using Numerics;
using Properties;
/// <summary> /// <summary>
/// <para>A class which encapsulates the functionality of a Cholesky factorization for dense matrices.</para> /// <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 /// 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. /// or positive definite, the constructor will throw an exception.
/// </remarks> /// </remarks>
public class DenseCholesky : Cholesky public sealed class DenseCholesky : Cholesky
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="DenseCholesky"/> class. This object will compute the /// 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="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 a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</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) if (matrix.RowCount != matrix.ColumnCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSquare); throw new ArgumentException(Resources.ArgumentMatrixSquare);
} }
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting). // 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); Control.LinearAlgebraProvider.CholeskyFactor(factor.Values, factor.RowCount);
Factor = factor; return new DenseCholesky(factor);
}
DenseCholesky(Matrix<Complex32> factor)
: base(factor)
{
} }
/// <summary> /// <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> /// <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) 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) if (result.RowCount != input.RowCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension); throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -121,7 +110,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor; var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, dresult.ColumnCount); 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> /// <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) 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) if (input.Count != result.Count)
{ {
throw new ArgumentException(Resources.ArgumentVectorsSameLength); throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -170,7 +147,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length); Array.Copy(dinput.Values, dresult.Values, dinput.Values.Length);
// Cholesky solve by overwriting result. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor; var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, 1); 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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,9 +28,9 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using System;
using MathNet.Numerics.Properties; using MathNet.Numerics.Properties;
using MathNet.Numerics.Threading; using MathNet.Numerics.Threading;
using System;
namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization 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 /// 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. /// or positive definite, the constructor will throw an exception.
/// </remarks> /// </remarks>
public class UserCholesky : Cholesky public sealed class UserCholesky : Cholesky
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UserCholesky"/> class. This object will compute the /// 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="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 a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</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) if (matrix.RowCount != matrix.ColumnCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSquare); throw new ArgumentException(Resources.ArgumentMatrixSquare);
} }
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting). // Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
Factor = matrix.Clone(); var factor = matrix.Clone();
var tmpColumn = new Complex32[Factor.RowCount]; var tmpColumn = new Complex32[factor.RowCount];
// Main loop - along the diagonal // Main loop - along the diagonal
for (var ij = 0; ij < Factor.RowCount; ij++) for (var ij = 0; ij < factor.RowCount; ij++)
{ {
// "Pivot" element // "Pivot" element
var tmpVal = Factor.At(ij, ij); var tmpVal = factor.At(ij, ij);
if (tmpVal.Real > 0.0) if (tmpVal.Real > 0.0)
{ {
tmpVal = tmpVal.SquareRoot(); tmpVal = tmpVal.SquareRoot();
Factor.At(ij, ij, tmpVal); factor.At(ij, ij, tmpVal);
tmpColumn[ij] = tmpVal; tmpColumn[ij] = tmpVal;
// Calculate multipliers and copy to local column // Calculate multipliers and copy to local column
// Current column, below the diagonal // 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); factor.At(i, ij, factor.At(i, ij)/tmpVal);
tmpColumn[i] = Factor.At(i, ij); tmpColumn[i] = factor.At(i, ij);
} }
// Remaining columns, below the diagonal // 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 else
{ {
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite); 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> /// <summary>
@ -115,14 +117,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
/// <param name="colLimit">Total columns</param> /// <param name="colLimit">Total columns</param>
/// <param name="multipliers">Multipliers calculated previously</param> /// <param name="multipliers">Multipliers calculated previously</param>
/// <param name="availableCores">Number of available processors</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; var tmpColCount = colLimit - firstCol;
if ((availableCores > 1) && (tmpColCount > 200)) if ((availableCores > 1) && (tmpColCount > 200))
{ {
var tmpSplit = firstCol + (tmpColCount / 3); var tmpSplit = firstCol + (tmpColCount/3);
var tmpCores = availableCores / 2; var tmpCores = availableCores/2;
CommonParallel.Invoke( CommonParallel.Invoke(
() => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores), () => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores),
@ -135,7 +137,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
var tmpVal = multipliers[j]; var tmpVal = multipliers[j];
for (var i = j; i < rowDim; i++) 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> /// <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) 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) if (result.RowCount != input.RowCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension); throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -186,10 +177,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
sum = result.At(i, c); sum = result.At(i, c);
for (var k = i - 1; k >= 0; k--) 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; // Solve L'*X = Y;
@ -198,10 +189,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
sum = result.At(i, c); sum = result.At(i, c);
for (var k = i + 1; k < order; k++) 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> /// <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) 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) if (input.Count != result.Count)
{ {
throw new ArgumentException(Resources.ArgumentVectorsSameLength); throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -245,10 +224,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
sum = result[i]; sum = result[i];
for (var k = i - 1; k >= 0; k--) 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; // Solve L'*X = Y;
@ -257,10 +236,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
sum = result[i]; sum = result[i];
for (var k = i + 1; k < order; k++) 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() public override Cholesky<Complex32> Cholesky()
{ {
return new UserCholesky(this); return UserCholesky.Create(this);
} }
public override LU<Complex32> LU() 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() public override Cholesky<double> Cholesky()
{ {
return new DenseCholesky(this); return DenseCholesky.Create(this);
} }
public override LU<double> LU() public override LU<double> LU()

11
src/Numerics/LinearAlgebra/Double/Factorization/Cholesky.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -45,6 +45,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// </remarks> /// </remarks>
public abstract class Cholesky : Cholesky<double> public abstract class Cholesky : Cholesky<double>
{ {
protected Cholesky(Matrix<double> factor)
: base(factor)
{
}
/// <summary> /// <summary>
/// Gets the determinant of the matrix for which the Cholesky matrix was computed. /// Gets the determinant of the matrix for which the Cholesky matrix was computed.
/// </summary> /// </summary>
@ -56,7 +61,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
for (var j = 0; j < Factor.RowCount; j++) for (var j = 0; j < Factor.RowCount; j++)
{ {
var d = Factor.At(j, j); var d = Factor.At(j, j);
det *= d * d; det *= d*d;
} }
return det; return det;
@ -73,7 +78,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
var det = 0.0; var det = 0.0;
for (var j = 0; j < Factor.RowCount; j++) 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; return det;

54
src/Numerics/LinearAlgebra/Double/Factorization/DenseCholesky.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,8 +28,8 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using MathNet.Numerics.Properties;
using System; using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Double.Factorization 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 /// 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. /// or positive definite, the constructor will throw an exception.
/// </remarks> /// </remarks>
public class DenseCholesky : Cholesky public sealed class DenseCholesky : Cholesky
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="DenseCholesky"/> class. This object will compute the /// 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="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 a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</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) if (matrix.RowCount != matrix.ColumnCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSquare); throw new ArgumentException(Resources.ArgumentMatrixSquare);
} }
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting). // 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); Control.LinearAlgebraProvider.CholeskyFactor(factor.Values, factor.RowCount);
Factor = factor; return new DenseCholesky(factor);
}
DenseCholesky(Matrix<double> factor)
: base(factor)
{
} }
/// <summary> /// <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> /// <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) 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) if (result.RowCount != input.RowCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension); throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -117,10 +105,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
} }
// Copy the contents of input to result. // 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. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor; var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, dresult.ColumnCount); 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> /// <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) 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) if (input.Count != result.Count)
{ {
throw new ArgumentException(Resources.ArgumentVectorsSameLength); throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -166,10 +142,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
} }
// Copy the contents of input to result. // 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. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor; var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, 1); 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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,9 +28,9 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using System;
using MathNet.Numerics.Properties; using MathNet.Numerics.Properties;
using MathNet.Numerics.Threading; using MathNet.Numerics.Threading;
using System;
namespace MathNet.Numerics.LinearAlgebra.Double.Factorization 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 /// 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. /// or positive definite, the constructor will throw an exception.
/// </remarks> /// </remarks>
public class UserCholesky : Cholesky public sealed class UserCholesky : Cholesky
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UserCholesky"/> class. This object will compute the /// 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="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 a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</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) if (matrix.RowCount != matrix.ColumnCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSquare); throw new ArgumentException(Resources.ArgumentMatrixSquare);
} }
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting). // Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
Factor = matrix.Clone(); var factor = matrix.Clone();
var tmpColumn = new double[Factor.RowCount]; var tmpColumn = new double[factor.RowCount];
// Main loop - along the diagonal // Main loop - along the diagonal
for (var ij = 0; ij < Factor.RowCount; ij++) for (var ij = 0; ij < factor.RowCount; ij++)
{ {
// "Pivot" element // "Pivot" element
var tmpVal = Factor.At(ij, ij); var tmpVal = factor.At(ij, ij);
if (tmpVal > 0.0) if (tmpVal > 0.0)
{ {
tmpVal = Math.Sqrt(tmpVal); tmpVal = Math.Sqrt(tmpVal);
Factor.At(ij, ij, tmpVal); factor.At(ij, ij, tmpVal);
tmpColumn[ij] = tmpVal; tmpColumn[ij] = tmpVal;
// Calculate multipliers and copy to local column // Calculate multipliers and copy to local column
// Current column, below the diagonal // 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); factor.At(i, ij, factor.At(i, ij)/tmpVal);
tmpColumn[i] = Factor.At(i, ij); tmpColumn[i] = factor.At(i, ij);
} }
// Remaining columns, below the diagonal // 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 else
{ {
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite); 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> /// <summary>
@ -113,14 +115,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
/// <param name="colLimit">Total columns</param> /// <param name="colLimit">Total columns</param>
/// <param name="multipliers">Multipliers calculated previously</param> /// <param name="multipliers">Multipliers calculated previously</param>
/// <param name="availableCores">Number of available processors</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; var tmpColCount = colLimit - firstCol;
if ((availableCores > 1) && (tmpColCount > 200)) if ((availableCores > 1) && (tmpColCount > 200))
{ {
var tmpSplit = firstCol + (tmpColCount / 3); var tmpSplit = firstCol + (tmpColCount/3);
var tmpCores = availableCores / 2; var tmpCores = availableCores/2;
CommonParallel.Invoke( CommonParallel.Invoke(
() => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores), () => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores),
@ -133,7 +135,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
var tmpVal = multipliers[j]; var tmpVal = multipliers[j];
for (var i = j; i < rowDim; i++) 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> /// <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) 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) if (result.RowCount != input.RowCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension); throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -184,10 +175,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
sum = result.At(i, c); sum = result.At(i, c);
for (var k = i - 1; k >= 0; k--) 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; // Solve L'*X = Y;
@ -196,10 +187,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
sum = result.At(i, c); sum = result.At(i, c);
for (var k = i + 1; k < order; k++) 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> /// <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) 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) if (input.Count != result.Count)
{ {
throw new ArgumentException(Resources.ArgumentVectorsSameLength); throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -243,10 +222,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
sum = result[i]; sum = result[i];
for (var k = i - 1; k >= 0; k--) 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; // Solve L'*X = Y;
@ -255,10 +234,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
sum = result[i]; sum = result[i];
for (var k = i + 1; k < order; k++) 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() public override Cholesky<double> Cholesky()
{ {
return new UserCholesky(this); return UserCholesky.Create(this);
} }
public override LU<double> LU() public override LU<double> LU()

23
src/Numerics/LinearAlgebra/Factorization/Cholesky.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -43,12 +43,17 @@ namespace MathNet.Numerics.LinearAlgebra.Factorization
/// </remarks> /// </remarks>
/// <typeparam name="T">Supported data types are double, single, <see cref="Complex"/>, and <see cref="Complex32"/>.</typeparam> /// <typeparam name="T">Supported data types are double, single, <see cref="Complex"/>, and <see cref="Complex32"/>.</typeparam>
public abstract class Cholesky<T> : ISolver<T> 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> /// <summary>
/// Gets the lower triangular form of the Cholesky matrix. /// Gets the lower triangular form of the Cholesky matrix.
/// </summary> /// </summary>
public Matrix<T> Factor { get; protected set; } public Matrix<T> Factor { get; private set; }
/// <summary> /// <summary>
/// Gets the determinant of the matrix for which the Cholesky matrix was computed. /// 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> /// <returns>The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</returns>
public virtual Matrix<T> Solve(Matrix<T> input) 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); var x = input.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(input, x); Solve(input, x);
return 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> /// <returns>The left hand side <see cref="Vector{T}"/>, <b>x</b>.</returns>
public virtual Vector<T> Solve(Vector<T> input) 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); var x = input.CreateVector(input.Count);
Solve(input, x); Solve(input, x);
return x; return x;

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

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

11
src/Numerics/LinearAlgebra/Single/Factorization/Cholesky.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -45,6 +45,11 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// </remarks> /// </remarks>
public abstract class Cholesky : Cholesky<float> public abstract class Cholesky : Cholesky<float>
{ {
protected Cholesky(Matrix<float> factor)
: base(factor)
{
}
/// <summary> /// <summary>
/// Gets the determinant of the matrix for which the Cholesky matrix was computed. /// Gets the determinant of the matrix for which the Cholesky matrix was computed.
/// </summary> /// </summary>
@ -56,7 +61,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
for (var j = 0; j < Factor.RowCount; j++) for (var j = 0; j < Factor.RowCount; j++)
{ {
var d = Factor.At(j, j); var d = Factor.At(j, j);
det *= d * d; det *= d*d;
} }
return det; return det;
@ -73,7 +78,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
var det = 0.0f; var det = 0.0f;
for (var j = 0; j < Factor.RowCount; j++) 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; return det;

54
src/Numerics/LinearAlgebra/Single/Factorization/DenseCholesky.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,8 +28,8 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using MathNet.Numerics.Properties;
using System; using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Single.Factorization 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 /// 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. /// or positive definite, the constructor will throw an exception.
/// </remarks> /// </remarks>
public class DenseCholesky : Cholesky public sealed class DenseCholesky : Cholesky
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="DenseCholesky"/> class. This object will compute the /// 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="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 a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</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) if (matrix.RowCount != matrix.ColumnCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSquare); throw new ArgumentException(Resources.ArgumentMatrixSquare);
} }
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting). // 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); Control.LinearAlgebraProvider.CholeskyFactor(factor.Values, factor.RowCount);
Factor = factor; return new DenseCholesky(factor);
}
DenseCholesky(Matrix<float> factor)
: base(factor)
{
} }
/// <summary> /// <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> /// <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) 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) if (result.RowCount != input.RowCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension); throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -117,10 +105,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
} }
// Copy the contents of input to result. // 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. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor; var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, dresult.ColumnCount); 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> /// <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) 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) if (input.Count != result.Count)
{ {
throw new ArgumentException(Resources.ArgumentVectorsSameLength); throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -166,10 +142,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
} }
// Copy the contents of input to result. // 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. // Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)Factor; var dfactor = (DenseMatrix) Factor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Values, dfactor.RowCount, dresult.Values, 1); 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://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // 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 // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,9 +28,9 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using System;
using MathNet.Numerics.Properties; using MathNet.Numerics.Properties;
using MathNet.Numerics.Threading; using MathNet.Numerics.Threading;
using System;
namespace MathNet.Numerics.LinearAlgebra.Single.Factorization 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 /// 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. /// or positive definite, the constructor will throw an exception.
/// </remarks> /// </remarks>
public class UserCholesky : Cholesky public sealed class UserCholesky : Cholesky
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UserCholesky"/> class. This object will compute the /// 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="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 a square matrix.</exception>
/// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</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) if (matrix.RowCount != matrix.ColumnCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSquare); throw new ArgumentException(Resources.ArgumentMatrixSquare);
} }
// Create a new matrix for the Cholesky factor, then perform factorization (while overwriting). // Create a new matrix for the Cholesky factor, then perform factorization (while overwriting).
Factor = matrix.Clone(); var factor = matrix.Clone();
var tmpColumn = new float[Factor.RowCount]; var tmpColumn = new float[factor.RowCount];
// Main loop - along the diagonal // Main loop - along the diagonal
for (var ij = 0; ij < Factor.RowCount; ij++) for (var ij = 0; ij < factor.RowCount; ij++)
{ {
// "Pivot" element // "Pivot" element
var tmpVal = Factor.At(ij, ij); var tmpVal = factor.At(ij, ij);
if (tmpVal > 0.0) if (tmpVal > 0.0)
{ {
tmpVal = (float)Math.Sqrt(tmpVal); tmpVal = (float) Math.Sqrt(tmpVal);
Factor.At(ij, ij, tmpVal); factor.At(ij, ij, tmpVal);
tmpColumn[ij] = tmpVal; tmpColumn[ij] = tmpVal;
// Calculate multipliers and copy to local column // Calculate multipliers and copy to local column
// Current column, below the diagonal // 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); factor.At(i, ij, factor.At(i, ij)/tmpVal);
tmpColumn[i] = Factor.At(i, ij); tmpColumn[i] = factor.At(i, ij);
} }
// Remaining columns, below the diagonal // 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 else
{ {
throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite); 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> /// <summary>
@ -113,14 +115,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
/// <param name="colLimit">Total columns</param> /// <param name="colLimit">Total columns</param>
/// <param name="multipliers">Multipliers calculated previously</param> /// <param name="multipliers">Multipliers calculated previously</param>
/// <param name="availableCores">Number of available processors</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; var tmpColCount = colLimit - firstCol;
if ((availableCores > 1) && (tmpColCount > 200)) if ((availableCores > 1) && (tmpColCount > 200))
{ {
var tmpSplit = firstCol + (tmpColCount / 3); var tmpSplit = firstCol + (tmpColCount/3);
var tmpCores = availableCores / 2; var tmpCores = availableCores/2;
CommonParallel.Invoke( CommonParallel.Invoke(
() => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores), () => DoCholeskyStep(data, rowDim, firstCol, tmpSplit, multipliers, tmpCores),
@ -133,7 +135,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
var tmpVal = multipliers[j]; var tmpVal = multipliers[j];
for (var i = j; i < rowDim; i++) 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> /// <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) 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) if (result.RowCount != input.RowCount)
{ {
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension); throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
@ -184,10 +175,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
sum = result.At(i, c); sum = result.At(i, c);
for (var k = i - 1; k >= 0; k--) 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; // Solve L'*X = Y;
@ -196,10 +187,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
sum = result.At(i, c); sum = result.At(i, c);
for (var k = i + 1; k < order; k++) 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> /// <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) 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) if (input.Count != result.Count)
{ {
throw new ArgumentException(Resources.ArgumentVectorsSameLength); throw new ArgumentException(Resources.ArgumentVectorsSameLength);
@ -243,10 +222,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
sum = result[i]; sum = result[i];
for (var k = i - 1; k >= 0; k--) 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; // Solve L'*X = Y;
@ -255,10 +234,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
sum = result[i]; sum = result[i];
for (var k = i + 1; k < order; k++) 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() public override Cholesky<float> Cholesky()
{ {
return new UserCholesky(this); return UserCholesky.Create(this);
} }
public override LU<float> LU() public override LU<float> LU()

Loading…
Cancel
Save