Compare commits

...

25 Commits
master ... v2

Author SHA1 Message Date
Christoph Ruegg ec6527a27d LA: Complex iterative solvers must use conjugated dot-product #128 13 years ago
Christoph Ruegg 4b9ac99d68 Vector: proper L1, L2 and infinity norms 13 years ago
Christoph Ruegg 33051dcc0c Vector: Added ConjugateDotProduct 13 years ago
Christoph Ruegg ed7827e2b7 Distance: SAD, MAE, SSD, MSE 13 years ago
Christoph Ruegg d501e26e04 Typo in inline docs (LogNormal) 13 years ago
Christoph Ruegg 9e2c0393b9 Distributions: maximum-likelihood estimation for normal, log-normal 13 years ago
Christoph Ruegg a017a10374 Statistics: single-pass MeanVariance method 13 years ago
Christoph Ruegg 5605204dbd Trig: robustify complex Asin/Acos for large real numbers 13 years ago
taschna 5e27553e02 RootFinding: Add higher dimensional test cases. 13 years ago
Christoph Ruegg e2d771946b BUG: Fix Hypergeometric CDF semantics, clarify distribution parameters 13 years ago
Christoph Ruegg 52eecf0926 BUG: Fix bug in ArrayStatistics.Variance on arrays longer than 46341 entries #137 13 years ago
Christoph Ruegg ca818de454 LA: Modulus between matrix and scalar; pointwise modulus; improved naming 13 years ago
Christoph Ruegg 42ea17070b LA: Leverage providers for scalar division 13 years ago
Christoph Ruegg 9d8b3e3342 LA: Devide a matrix by a scalar, or a scalar by a matrix 13 years ago
Christoph Ruegg dc7c8a9960 LA: Subtract a scalar from a matrix, and a matrix from a scalar 13 years ago
Christoph Ruegg 24f3df3260 LA: Add a scalar to a matrix 13 years ago
Christoph Ruegg 8155eb03b4 LA: Collect vector arithmetics in separate file 13 years ago
Christoph Ruegg b88fdec943 Portable: SpecialName attribute backport 13 years ago
Christoph Ruegg 59ac7b04aa LA: Collect vector operators in separate file 13 years ago
Christoph Ruegg acf192339b LA: Collect matrix operators in separate file 13 years ago
Christoph Ruegg 0c41bdbf9d LA: Support for pointwise .*, ./ and .% operators where supported (F# for now) 13 years ago
Christoph Ruegg 9ef78cc3b7 Distributions: formatting cleanup (no code changes) 13 years ago
Christoph Ruegg 77fa705335 Distributions: ctor overloads that accept Random argument 13 years ago
Christoph Ruegg 17efeb959a Simplify root files slightly 13 years ago
Christoph Ruegg da4a47ff9e Update text file links in solution (release notes etc) 13 years ago
  1. 9
      MathNet.Numerics.sln
  2. 8
      src/Examples/DiscreteDistributions/HypergeometricDistribution.cs
  3. 8
      src/Examples/LinearAlgebra/MatrixNorms.cs
  4. 14
      src/FSharpUnitTests/MatrixTests.fs
  5. 15
      src/FSharpUnitTests/VectorTests.fs
  6. 189
      src/Numerics/Distance.cs
  7. 44
      src/Numerics/Distributions/Continuous/Beta.cs
  8. 42
      src/Numerics/Distributions/Continuous/Cauchy.cs
  9. 37
      src/Numerics/Distributions/Continuous/Chi.cs
  10. 38
      src/Numerics/Distributions/Continuous/ChiSquare.cs
  11. 39
      src/Numerics/Distributions/Continuous/ContinuousUniform.cs
  12. 78
      src/Numerics/Distributions/Continuous/Erlang.cs
  13. 35
      src/Numerics/Distributions/Continuous/Exponential.cs
  14. 41
      src/Numerics/Distributions/Continuous/FisherSnedecor.cs
  15. 68
      src/Numerics/Distributions/Continuous/Gamma.cs
  16. 43
      src/Numerics/Distributions/Continuous/InverseGamma.cs
  17. 42
      src/Numerics/Distributions/Continuous/Laplace.cs
  18. 90
      src/Numerics/Distributions/Continuous/LogNormal.cs
  19. 113
      src/Numerics/Distributions/Continuous/Normal.cs
  20. 48
      src/Numerics/Distributions/Continuous/Pareto.cs
  21. 44
      src/Numerics/Distributions/Continuous/Rayleigh.cs
  22. 69
      src/Numerics/Distributions/Continuous/Stable.cs
  23. 61
      src/Numerics/Distributions/Continuous/StudentT.cs
  24. 43
      src/Numerics/Distributions/Continuous/Weibull.cs
  25. 24
      src/Numerics/Distributions/Discrete/Bernoulli.cs
  26. 41
      src/Numerics/Distributions/Discrete/Binomial.cs
  27. 26
      src/Numerics/Distributions/Discrete/Categorical.cs
  28. 81
      src/Numerics/Distributions/Discrete/ConwayMaxwellPoisson.cs
  29. 33
      src/Numerics/Distributions/Discrete/DiscreteUniform.cs
  30. 33
      src/Numerics/Distributions/Discrete/Geometric.cs
  31. 249
      src/Numerics/Distributions/Discrete/Hypergeometric.cs
  32. 40
      src/Numerics/Distributions/Discrete/NegativeBinomial.cs
  33. 44
      src/Numerics/Distributions/Discrete/Poisson.cs
  34. 43
      src/Numerics/Distributions/Discrete/Zipf.cs
  35. 100
      src/Numerics/Distributions/Multivariate/Dirichlet.cs
  36. 92
      src/Numerics/Distributions/Multivariate/InverseWishart.cs
  37. 101
      src/Numerics/Distributions/Multivariate/MatrixNormal.cs
  38. 76
      src/Numerics/Distributions/Multivariate/Multinomial.cs
  39. 164
      src/Numerics/Distributions/Multivariate/NormalGamma.cs
  40. 92
      src/Numerics/Distributions/Multivariate/Wishart.cs
  41. 54
      src/Numerics/IPrecisionSupport.cs
  42. 76
      src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs
  43. 122
      src/Numerics/LinearAlgebra/Complex/DenseVector.cs
  44. 2
      src/Numerics/LinearAlgebra/Complex/Factorization/UserGramSchmidt.cs
  45. 84
      src/Numerics/LinearAlgebra/Complex/Matrix.cs
  46. 49
      src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/BiCgStab.cs
  47. 15
      src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/GpBiCg.cs
  48. 89
      src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/MlkBiCgStab.cs
  49. 13
      src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/TFQMR.cs
  50. 2
      src/Numerics/LinearAlgebra/Complex/Solvers/Preconditioners/Ilutp.cs
  51. 2
      src/Numerics/LinearAlgebra/Complex/Solvers/StopCriterium/DivergenceStopCriterium.cs
  52. 4
      src/Numerics/LinearAlgebra/Complex/Solvers/StopCriterium/FailureStopCriterium.cs
  53. 4
      src/Numerics/LinearAlgebra/Complex/Solvers/StopCriterium/ResidualStopCriterium.cs
  54. 6
      src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs
  55. 120
      src/Numerics/LinearAlgebra/Complex/SparseVector.cs
  56. 95
      src/Numerics/LinearAlgebra/Complex/Vector.cs
  57. 76
      src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs
  58. 122
      src/Numerics/LinearAlgebra/Complex32/DenseVector.cs
  59. 2
      src/Numerics/LinearAlgebra/Complex32/Factorization/UserGramSchmidt.cs
  60. 84
      src/Numerics/LinearAlgebra/Complex32/Matrix.cs
  61. 48
      src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/BiCgStab.cs
  62. 14
      src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/GpBiCg.cs
  63. 90
      src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/MlkBiCgStab.cs
  64. 12
      src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/TFQMR.cs
  65. 2
      src/Numerics/LinearAlgebra/Complex32/Solvers/Preconditioners/Ilutp.cs
  66. 2
      src/Numerics/LinearAlgebra/Complex32/Solvers/StopCriterium/DivergenceStopCriterium.cs
  67. 4
      src/Numerics/LinearAlgebra/Complex32/Solvers/StopCriterium/FailureStopCriterium.cs
  68. 4
      src/Numerics/LinearAlgebra/Complex32/Solvers/StopCriterium/ResidualStopCriterium.cs
  69. 6
      src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs
  70. 122
      src/Numerics/LinearAlgebra/Complex32/SparseVector.cs
  71. 97
      src/Numerics/LinearAlgebra/Complex32/Vector.cs
  72. 98
      src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
  73. 110
      src/Numerics/LinearAlgebra/Double/DenseVector.cs
  74. 66
      src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs
  75. 2
      src/Numerics/LinearAlgebra/Double/Factorization/UserGramSchmidt.cs
  76. 108
      src/Numerics/LinearAlgebra/Double/Matrix.cs
  77. 2
      src/Numerics/LinearAlgebra/Double/Solvers/Iterative/MlkBiCgStab.cs
  78. 10
      src/Numerics/LinearAlgebra/Double/Solvers/Iterative/TFQMR.cs
  79. 2
      src/Numerics/LinearAlgebra/Double/Solvers/Preconditioners/Ilutp.cs
  80. 2
      src/Numerics/LinearAlgebra/Double/Solvers/StopCriterium/DivergenceStopCriterium.cs
  81. 4
      src/Numerics/LinearAlgebra/Double/Solvers/StopCriterium/FailureStopCriterium.cs
  82. 4
      src/Numerics/LinearAlgebra/Double/Solvers/StopCriterium/ResidualStopCriterium.cs
  83. 6
      src/Numerics/LinearAlgebra/Double/SparseMatrix.cs
  84. 101
      src/Numerics/LinearAlgebra/Double/SparseVector.cs
  85. 118
      src/Numerics/LinearAlgebra/Double/Vector.cs
  86. 535
      src/Numerics/LinearAlgebra/Generic/Matrix.Arithmetic.cs
  87. 386
      src/Numerics/LinearAlgebra/Generic/Matrix.Operators.cs
  88. 1002
      src/Numerics/LinearAlgebra/Generic/Vector.Arithmetic.cs
  89. 349
      src/Numerics/LinearAlgebra/Generic/Vector.Operators.cs
  90. 1242
      src/Numerics/LinearAlgebra/Generic/Vector.cs
  91. 98
      src/Numerics/LinearAlgebra/Single/DenseMatrix.cs
  92. 113
      src/Numerics/LinearAlgebra/Single/DenseVector.cs
  93. 66
      src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs
  94. 2
      src/Numerics/LinearAlgebra/Single/Factorization/UserGramSchmidt.cs
  95. 96
      src/Numerics/LinearAlgebra/Single/Matrix.cs
  96. 2
      src/Numerics/LinearAlgebra/Single/Solvers/Iterative/MlkBiCgStab.cs
  97. 8
      src/Numerics/LinearAlgebra/Single/Solvers/Iterative/TFQMR.cs
  98. 2
      src/Numerics/LinearAlgebra/Single/Solvers/Preconditioners/Ilutp.cs
  99. 2
      src/Numerics/LinearAlgebra/Single/Solvers/StopCriterium/DivergenceStopCriterium.cs
  100. 4
      src/Numerics/LinearAlgebra/Single/Solvers/StopCriterium/FailureStopCriterium.cs

9
MathNet.Numerics.sln

@ -7,9 +7,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{49EE
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Readme", "Readme", "{C2F37492-38AE-4186-8A7F-17B0B080942C}"
ProjectSection(SolutionItems) = preProject
AUTHORS.markdown = AUTHORS.markdown
COPYRIGHT.markdown = COPYRIGHT.markdown
README.markdown = README.markdown
CONTRIBUTING.md = CONTRIBUTING.md
CONTRIBUTORS.md = CONTRIBUTORS.md
LICENSE.md = LICENSE.md
MAINTAINING.md = MAINTAINING.md
README.md = README.md
RELEASENOTES.md = RELEASENOTES.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples", "src\Examples\Examples.csproj", "{8239A6FF-1EF3-4DA4-A860-95C392DD6899}"

8
src/Examples/DiscreteDistributions/HypergeometricDistribution.cs

@ -65,7 +65,7 @@ namespace Examples.DiscreteDistributionsExamples
{
// 1. Initialize the new instance of the Hypergeometric distribution class with parameters PopulationSize = 10, M = 2, N = 8
var hypergeometric = new Hypergeometric(30, 15, 10);
Console.WriteLine(@"1. Initialize the new instance of the Hypergeometric distribution class with parameters PopulationSize = {0}, M = {1}, N = {2}", hypergeometric.PopulationSize, hypergeometric.M, hypergeometric.N);
Console.WriteLine(@"1. Initialize the new instance of the Hypergeometric distribution class with parameters Population = {0}, Success = {1}, Draws = {2}", hypergeometric.Population, hypergeometric.Success, hypergeometric.Draws);
Console.WriteLine();
// 2. Distributuion properties:
@ -125,9 +125,9 @@ namespace Examples.DiscreteDistributionsExamples
// 5. Generate 100000 samples of the Hypergeometric(52, 13, 5) distribution and display histogram
Console.WriteLine(@"5. Generate 100000 samples of the Hypergeometric(52, 13, 5) distribution and display histogram");
hypergeometric.PopulationSize = 52;
hypergeometric.M = 13;
hypergeometric.N = 5;
hypergeometric.Population = 52;
hypergeometric.Success = 13;
hypergeometric.Draws = 5;
for (var i = 0; i < data.Length; i++)
{
data[i] = hypergeometric.Sample();

8
src/Examples/LinearAlgebra/MatrixNorms.cs

@ -97,7 +97,7 @@ namespace Examples.LinearAlgebraExamples
Console.WriteLine(@"5. Normalize matrix columns: before normalize");
foreach (var keyValuePair in matrix.ColumnEnumerator())
{
Console.WriteLine(@"Column {0} 2-nd norm is: {1}", keyValuePair.Item1, keyValuePair.Item2.Norm(2));
Console.WriteLine(@"Column {0} 2-nd norm is: {1}", keyValuePair.Item1, keyValuePair.Item2.L2Norm());
}
Console.WriteLine();
@ -105,7 +105,7 @@ namespace Examples.LinearAlgebraExamples
Console.WriteLine(@"5. Normalize matrix columns: after normalize");
foreach (var keyValuePair in normalized.ColumnEnumerator())
{
Console.WriteLine(@"Column {0} 2-nd norm is: {1}", keyValuePair.Item1, keyValuePair.Item2.Norm(2));
Console.WriteLine(@"Column {0} 2-nd norm is: {1}", keyValuePair.Item1, keyValuePair.Item2.L2Norm());
}
Console.WriteLine();
@ -114,7 +114,7 @@ namespace Examples.LinearAlgebraExamples
Console.WriteLine(@"6. Normalize matrix rows: before normalize");
foreach (var keyValuePair in matrix.RowEnumerator())
{
Console.WriteLine(@"Row {0} 2-nd norm is: {1}", keyValuePair.Item1, keyValuePair.Item2.Norm(2));
Console.WriteLine(@"Row {0} 2-nd norm is: {1}", keyValuePair.Item1, keyValuePair.Item2.L2Norm());
}
Console.WriteLine();
@ -122,7 +122,7 @@ namespace Examples.LinearAlgebraExamples
Console.WriteLine(@"6. Normalize matrix rows: after normalize");
foreach (var keyValuePair in normalized.RowEnumerator())
{
Console.WriteLine(@"Row {0} 2-nd norm is: {1}", keyValuePair.Item1, keyValuePair.Item2.Norm(2));
Console.WriteLine(@"Row {0} 2-nd norm is: {1}", keyValuePair.Item1, keyValuePair.Item2.L2Norm());
}
}
}

14
src/FSharpUnitTests/MatrixTests.fs

@ -10,14 +10,14 @@ module MatrixTests =
let approximately_equal tolerance = equalWithin (10.0 ** (float -tolerance))
/// A small uniform vector.
/// A small uniform matrix.
let smallM = DenseMatrix.OfArray( Array2D.create 2 2 0.3 )
let failingFoldBackM = DenseMatrix.init 2 3 (fun i j -> 1.0)
/// A small sparse matrix.
let sparseM = SparseMatrix.ofListi 2 3 [(1,0,0.3)]
/// A large vector with increasingly large entries
/// A large matrix with increasingly large entries
let largeM = DenseMatrix.OfArray( Array2D.init 100 100 (fun i j -> float i * 100.0 + float j) )
[<Test>]
@ -179,3 +179,13 @@ module MatrixTests =
[<Test>]
let ``Matrix.foldByRow`` () =
Matrix.foldByRow (+) 0.0 smallM |> should equal (DenseVector.ofList [0.6;0.6] :> Vector<float>)
[<Test>]
let ``Pointwise Multiplication using .* Operator`` () =
let z = largeM .* largeM
z |> should equal (DenseMatrix.init 100 100 (fun i j -> (float i * 100.0 + float j) ** 2.0))
[<Test>]
let ``Pointwise Division using ./ Operator`` () =
let z = largeM ./ DenseMatrix.create 100 100 2.0
z |> should equal (largeM * 0.5)

15
src/FSharpUnitTests/VectorTests.fs

@ -164,3 +164,18 @@ module VectorTests =
[<Test>]
let ``Vector.insert`` () =
Vector.insert 2 0.5 smallv |> should (approximately_equal 14) (new DenseVector ( [|0.3;0.3;0.5;0.3;0.3;0.3|] ) :> Vector<float>)
[<Test>]
let ``Pointwise Multiplication using .* Operator`` () =
let z = largev .* largev
z |> should equal (DenseVector.init 100 (fun i -> (float i / 100.0) ** 2.0))
[<Test>]
let ``Pointwise Division using ./ Operator`` () =
let z = largev ./ DenseVector.create 100 2.0
z |> should equal (largev * 0.5)
[<Test>]
let ``Pointwise Modulus using .% Operator`` () =
let z = largev .% DenseVector.create 100 2.0
z |> should equal (largev % 2.0)

189
src/Numerics/Distance.cs

@ -0,0 +1,189 @@
// <copyright file="Distance.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Generic;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics
{
public static class Distance
{
/// <summary>
/// Sum of Absolute Difference (SAD), i.e. the L1-norm (Manhattan) of the difference.
/// </summary>
public static double SAD(Vector<double> a, Vector<double> b)
{
return (a - b).L1Norm();
}
/// <summary>
/// Sum of Absolute Difference (SAD), i.e. the L1-norm (Manhattan) of the difference.
/// </summary>
public static float SAD(Vector<float> a, Vector<float> b)
{
return (a - b).L1Norm();
}
/// <summary>
/// Sum of Absolute Difference (SAD), i.e. the L1-norm (Manhattan) of the difference.
/// </summary>
public static double SAD(double[] a, double[] b)
{
if (a.Length != b.Length) throw new ArgumentException(Resources.ArgumentVectorsSameLength);
var sum = 0d;
for (var i = 0; i < a.Length; i++)
{
sum += Math.Abs(a[i] - b[i]);
}
return sum;
}
/// <summary>
/// Sum of Absolute Difference (SAD), i.e. the L1-norm (Manhattan) of the difference.
/// </summary>
public static float SAD(float[] a, float[] b)
{
if (a.Length != b.Length) throw new ArgumentException(Resources.ArgumentVectorsSameLength);
var sum = 0f;
for (var i = 0; i < a.Length; i++)
{
sum += Math.Abs(a[i] - b[i]);
}
return sum;
}
/// <summary>
/// Mean-Absolute Error (MAE), i.e. the normalized L1-norm (Manhattan) of the difference.
/// </summary>
public static double MAE(Vector<double> a, Vector<double> b)
{
return (a - b).L1Norm()/a.Count;
}
/// <summary>
/// Mean-Absolute Error (MAE), i.e. the normalized L1-norm (Manhattan) of the difference.
/// </summary>
public static float MAE(Vector<float> a, Vector<float> b)
{
return (a - b).L1Norm()/a.Count;
}
/// <summary>
/// Mean-Absolute Error (MAE), i.e. the normalized L1-norm (Manhattan) of the difference.
/// </summary>
public static double MAE(double[] a, double[] b)
{
return SAD(a, b)/a.Length;
}
/// <summary>
/// Mean-Absolute Error (MAE), i.e. the normalized L1-norm (Manhattan) of the difference.
/// </summary>
public static float MAE(float[] a, float[] b)
{
return SAD(a, b)/a.Length;
}
/// <summary>
/// Sum of Squared Difference (SSD), i.e. the squared L2-norm (Euclidean) of the difference.
/// </summary>
public static double SSD(Vector<double> a, Vector<double> b)
{
var norm = (a - b).L2Norm();
return norm*norm;
}
/// <summary>
/// Sum of Squared Difference (SSD), i.e. the squared L2-norm (Euclidean) of the difference.
/// </summary>
public static float SSD(Vector<float> a, Vector<float> b)
{
var norm = (a - b).L2Norm();
return norm*norm;
}
/// <summary>
/// Sum of Squared Difference (SSD), i.e. the squared L2-norm (Euclidean) of the difference.
/// </summary>
public static double SSD(double[] a, double[] b)
{
var diff = new double[a.Length];
Control.LinearAlgebraProvider.SubtractArrays(a, b, diff);
return Control.LinearAlgebraProvider.DotProduct(diff, diff);
}
/// <summary>
/// Sum of Squared Difference (SSD), i.e. the squared L2-norm (Euclidean) of the difference.
/// </summary>
public static float SSD(float[] a, float[] b)
{
var diff = new float[a.Length];
Control.LinearAlgebraProvider.SubtractArrays(a, b, diff);
return Control.LinearAlgebraProvider.DotProduct(diff, diff);
}
/// <summary>
/// Mean-Squared Error (MSE), i.e. the normalized squared L2-norm (Euclidean) of the difference.
/// </summary>
public static double MSE(Vector<double> a, Vector<double> b)
{
var norm = (a - b).L2Norm();
return norm*norm/a.Count;
}
/// <summary>
/// Mean-Squared Error (MSE), i.e. the normalized squared L2-norm (Euclidean) of the difference.
/// </summary>
public static float MSE(Vector<float> a, Vector<float> b)
{
var norm = (a - b).L2Norm();
return norm*norm/a.Count;
}
/// <summary>
/// Mean-Squared Error (MSE), i.e. the normalized squared L2-norm (Euclidean) of the difference.
/// </summary>
public static double MSE(double[] a, double[] b)
{
return SSD(a, b)/a.Length;
}
/// <summary>
/// Mean-Squared Error (MSE), i.e. the normalized squared L2-norm (Euclidean) of the difference.
/// </summary>
public static float MSE(float[] a, float[] b)
{
return SSD(a, b)/a.Length;
}
}
}

44
src/Numerics/Distributions/Continuous/Beta.cs

@ -71,8 +71,21 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="ArgumentOutOfRangeException">If any of the Beta parameters are negative.</exception>
public Beta(double a, double b)
{
_random = new Random();
SetParameters(a, b);
}
/// <summary>
/// Initializes a new instance of the Beta class.
/// </summary>
/// <param name="a">The a shape parameter of the Beta distribution.</param>
/// <param name="b">The b shape parameter of the Beta distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentOutOfRangeException">If any of the Beta parameters are negative.</exception>
public Beta(double a, double b, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(a, b);
RandomSource = new Random();
}
/// <summary>
@ -143,7 +156,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -192,7 +204,7 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
return _shapeA / (_shapeA + _shapeB);
return _shapeA/(_shapeA + _shapeB);
}
}
@ -201,7 +213,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return (_shapeA * _shapeB) / ((_shapeA + _shapeB) * (_shapeA + _shapeB) * (_shapeA + _shapeB + 1.0)); }
get { return (_shapeA*_shapeB)/((_shapeA + _shapeB)*(_shapeA + _shapeB)*(_shapeA + _shapeB + 1.0)); }
}
/// <summary>
@ -209,7 +221,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return Math.Sqrt((_shapeA * _shapeB) / ((_shapeA + _shapeB) * (_shapeA + _shapeB) * (_shapeA + _shapeB + 1.0))); }
get { return Math.Sqrt((_shapeA*_shapeB)/((_shapeA + _shapeB)*(_shapeA + _shapeB)*(_shapeA + _shapeB + 1.0))); }
}
/// <summary>
@ -235,9 +247,9 @@ namespace MathNet.Numerics.Distributions
}
return SpecialFunctions.BetaLn(_shapeA, _shapeB)
- ((_shapeA - 1.0) * SpecialFunctions.DiGamma(_shapeA))
- ((_shapeB - 1.0) * SpecialFunctions.DiGamma(_shapeB))
+ ((_shapeA + _shapeB - 2.0) * SpecialFunctions.DiGamma(_shapeA + _shapeB));
- ((_shapeA - 1.0)*SpecialFunctions.DiGamma(_shapeA))
- ((_shapeB - 1.0)*SpecialFunctions.DiGamma(_shapeB))
+ ((_shapeA + _shapeB - 2.0)*SpecialFunctions.DiGamma(_shapeA + _shapeB));
}
}
@ -278,8 +290,8 @@ namespace MathNet.Numerics.Distributions
return -2.0;
}
return 2.0 * (_shapeB - _shapeA) * Math.Sqrt(_shapeA + _shapeB + 1.0)
/ ((_shapeA + _shapeB + 2.0) * Math.Sqrt(_shapeA * _shapeB));
return 2.0*(_shapeB - _shapeA)*Math.Sqrt(_shapeA + _shapeB + 1.0)
/((_shapeA + _shapeB + 2.0)*Math.Sqrt(_shapeA*_shapeB));
}
}
@ -329,7 +341,7 @@ namespace MathNet.Numerics.Distributions
return 0.5;
}
return (_shapeA - 1) / (_shapeA + _shapeB - 2);
return (_shapeA - 1)/(_shapeA + _shapeB - 2);
}
}
@ -409,8 +421,8 @@ namespace MathNet.Numerics.Distributions
return 1.0;
}
var b = SpecialFunctions.Gamma(_shapeA + _shapeB) / (SpecialFunctions.Gamma(_shapeA) * SpecialFunctions.Gamma(_shapeB));
return b * Math.Pow(x, _shapeA - 1.0) * Math.Pow(1.0 - x, _shapeB - 1.0);
var b = SpecialFunctions.Gamma(_shapeA + _shapeB)/(SpecialFunctions.Gamma(_shapeA)*SpecialFunctions.Gamma(_shapeB));
return b*Math.Pow(x, _shapeA - 1.0)*Math.Pow(1.0 - x, _shapeB - 1.0);
}
/// <summary>
@ -466,8 +478,8 @@ namespace MathNet.Numerics.Distributions
}
var a = SpecialFunctions.GammaLn(_shapeA + _shapeB) - SpecialFunctions.GammaLn(_shapeA) - SpecialFunctions.GammaLn(_shapeB);
var b = x == 0.0 ? (_shapeA == 1.0 ? 0.0 : Double.NegativeInfinity) : (_shapeA - 1.0) * Math.Log(x);
var c = x == 1.0 ? (_shapeB == 1.0 ? 0.0 : Double.NegativeInfinity) : (_shapeB - 1.0) * Math.Log(1.0 - x);
var b = x == 0.0 ? (_shapeA == 1.0 ? 0.0 : Double.NegativeInfinity) : (_shapeA - 1.0)*Math.Log(x);
var c = x == 1.0 ? (_shapeB == 1.0 ? 0.0 : Double.NegativeInfinity) : (_shapeB - 1.0)*Math.Log(1.0 - x);
return a + b + c;
}
@ -545,7 +557,7 @@ namespace MathNet.Numerics.Distributions
{
var x = Gamma.SampleUnchecked(rnd, a, 1.0);
var y = Gamma.SampleUnchecked(rnd, b, 1.0);
return x / (x + y);
return x/(x + y);
}
/// <summary>

42
src/Numerics/Distributions/Continuous/Cauchy.cs

@ -54,27 +54,33 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="Cauchy"/> class with the location parameter set to 0 and the scale parameter set to 1
/// </summary>
public Cauchy()
: this(0, 1)
public Cauchy() : this(0, 1)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Cauchy"/> class.
/// </summary>
/// <param name="location">
/// The location parameter for the distribution.
/// </param>
/// <param name="scale">
/// The scale parameter for the distribution.
/// </param>
/// <exception cref="ArgumentException">
/// If <paramref name="scale"/> is negative.
/// </exception>
/// <param name="location">The location parameter for the distribution.</param>
/// <param name="scale">The scale parameter for the distribution.</param>
/// <exception cref="ArgumentException">If <paramref name="scale"/> is negative.</exception>
public Cauchy(double location, double scale)
{
_random = new Random();
SetParameters(location, scale);
}
/// <summary>
/// Initializes a new instance of the <see cref="Cauchy"/> class.
/// </summary>
/// <param name="location">The location parameter for the distribution.</param>
/// <param name="scale">The scale parameter for the distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentException">If <paramref name="scale"/> is negative.</exception>
public Cauchy(double location, double scale, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(location, scale);
RandomSource = new Random();
}
/// <summary>
@ -121,7 +127,6 @@ namespace MathNet.Numerics.Distributions
public double Location
{
get { return Median; }
set { SetParameters(value, _scale); }
}
@ -131,7 +136,6 @@ namespace MathNet.Numerics.Distributions
public double Scale
{
get { return _scale; }
set { SetParameters(Median, value); }
}
@ -192,7 +196,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Entropy
{
get { return Math.Log(4.0 * Constants.Pi * _scale); }
get { return Math.Log(4.0*Constants.Pi*_scale); }
}
/// <summary>
@ -210,7 +214,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
return ((1.0 / Constants.Pi) * Math.Atan((x - Median) / _scale)) + 0.5;
return ((1.0/Constants.Pi)*Math.Atan((x - Median)/_scale)) + 0.5;
}
#endregion
@ -253,7 +257,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the density at <paramref name="x"/>.</returns>
public double Density(double x)
{
return 1.0 / (Constants.Pi * _scale * (1.0 + (((x - Median) / _scale) * ((x - Median) / _scale))));
return 1.0/(Constants.Pi*_scale*(1.0 + (((x - Median)/_scale)*((x - Median)/_scale))));
}
/// <summary>
@ -263,7 +267,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the log density at <paramref name="x"/>.</returns>
public double DensityLn(double x)
{
return -Math.Log(Constants.Pi * _scale * (1.0 + (((x - Median) / _scale) * ((x - Median) / _scale))));
return -Math.Log(Constants.Pi*_scale*(1.0 + (((x - Median)/_scale)*((x - Median)/_scale))));
}
#endregion
@ -278,7 +282,7 @@ namespace MathNet.Numerics.Distributions
internal static double SampleUnchecked(Random rnd, double location, double scale)
{
var u = rnd.NextDouble();
return location + (scale * Math.Tan(Constants.Pi * (u - 0.5)));
return location + (scale*Math.Tan(Constants.Pi*(u - 0.5)));
}
/// <summary>

37
src/Numerics/Distributions/Continuous/Chi.cs

@ -57,13 +57,22 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="Chi"/> class.
/// </summary>
/// <param name="dof">
/// The degrees of freedom for the Chi distribution.
/// </param>
/// <param name="dof">The degrees of freedom for the Chi distribution.</param>
public Chi(double dof)
{
_random = new Random();
SetParameters(dof);
}
/// <summary>
/// Initializes a new instance of the <see cref="Chi"/> class.
/// </summary>
/// <param name="dof">The degrees of freedom for the Chi distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Chi(double dof, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(dof);
RandomSource = new Random();
}
/// <summary>
@ -102,7 +111,6 @@ namespace MathNet.Numerics.Distributions
public double DegreesOfFreedom
{
get { return _dof; }
set { SetParameters(value); }
}
@ -123,7 +131,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -140,7 +147,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return Math.Sqrt(2) * (SpecialFunctions.Gamma((_dof + 1.0) / 2.0) / SpecialFunctions.Gamma(_dof / 2.0)); }
get { return Math.Sqrt(2)*(SpecialFunctions.Gamma((_dof + 1.0)/2.0)/SpecialFunctions.Gamma(_dof/2.0)); }
}
/// <summary>
@ -148,7 +155,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return _dof - (Mean * Mean); }
get { return _dof - (Mean*Mean); }
}
/// <summary>
@ -164,7 +171,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Entropy
{
get { return SpecialFunctions.GammaLn(_dof / 2.0) + ((_dof - Math.Log(2) - ((_dof - 1.0) * SpecialFunctions.DiGamma(_dof / 2.0))) / 2.0); }
get { return SpecialFunctions.GammaLn(_dof/2.0) + ((_dof - Math.Log(2) - ((_dof - 1.0)*SpecialFunctions.DiGamma(_dof/2.0)))/2.0); }
}
/// <summary>
@ -175,7 +182,7 @@ namespace MathNet.Numerics.Distributions
get
{
var sigma = StdDev;
return (Mean * (1.0 - (2.0 * (sigma * sigma)))) / (sigma * sigma * sigma);
return (Mean*(1.0 - (2.0*(sigma*sigma))))/(sigma*sigma*sigma);
}
}
@ -186,7 +193,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
return SpecialFunctions.GammaLowerIncomplete(_dof / 2.0, x * x / 2.0) / SpecialFunctions.Gamma(_dof / 2.0);
return SpecialFunctions.GammaLowerIncomplete(_dof/2.0, x*x/2.0)/SpecialFunctions.Gamma(_dof/2.0);
}
#endregion
@ -240,7 +247,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the density at <paramref name="x"/>.</returns>
public double Density(double x)
{
return (Math.Pow(2.0, 1.0 - (_dof / 2.0)) * Math.Pow(x, _dof - 1.0) * Math.Exp(-x * x / 2.0)) / SpecialFunctions.Gamma(_dof / 2.0);
return (Math.Pow(2.0, 1.0 - (_dof/2.0))*Math.Pow(x, _dof - 1.0)*Math.Exp(-x*x/2.0))/SpecialFunctions.Gamma(_dof/2.0);
}
/// <summary>
@ -250,7 +257,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the log density at <paramref name="x"/>.</returns>
public double DensityLn(double x)
{
return ((1.0 - (_dof / 2.0)) * Math.Log(2.0)) + ((_dof - 1.0) * Math.Log(x)) - (x * x / 2.0) - SpecialFunctions.GammaLn(_dof / 2.0);
return ((1.0 - (_dof/2.0))*Math.Log(2.0)) + ((_dof - 1.0)*Math.Log(x)) - (x*x/2.0) - SpecialFunctions.GammaLn(_dof/2.0);
}
#endregion
@ -278,7 +285,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a sample from the distribution.</returns>
public double Sample()
{
return SampleUnchecked(RandomSource, (int)_dof);
return SampleUnchecked(RandomSource, (int) _dof);
}
/// <summary>
@ -287,7 +294,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a sequence of samples from the distribution.</returns>
public IEnumerable<double> Samples()
{
var dof = (int)_dof;
var dof = (int) _dof;
while (true)
{
yield return SampleUnchecked(RandomSource, dof);

38
src/Numerics/Distributions/Continuous/ChiSquare.cs

@ -54,13 +54,22 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="ChiSquare"/> class.
/// </summary>
/// <param name="dof">
/// The degrees of freedom for the ChiSquare distribution.
/// </param>
/// <param name="dof">The degrees of freedom for the ChiSquare distribution.</param>
public ChiSquare(double dof)
{
_random = new Random();
SetParameters(dof);
}
/// <summary>
/// Initializes a new instance of the <see cref="ChiSquare"/> class.
/// </summary>
/// <param name="dof">The degrees of freedom for the ChiSquare distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public ChiSquare(double dof, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(dof);
RandomSource = new Random();
}
/// <summary>
@ -94,7 +103,6 @@ namespace MathNet.Numerics.Distributions
public double DegreesOfFreedom
{
get { return Mean; }
set { SetParameters(value); }
}
@ -136,7 +144,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return 2.0 * Mean; }
get { return 2.0*Mean; }
}
/// <summary>
@ -144,7 +152,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return Math.Sqrt(2.0 * Mean); }
get { return Math.Sqrt(2.0*Mean); }
}
/// <summary>
@ -152,7 +160,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Entropy
{
get { return (Mean / 2.0) + Math.Log(2.0 * SpecialFunctions.Gamma(Mean / 2.0)) + ((1.0 - (Mean / 2.0)) * SpecialFunctions.DiGamma(Mean / 2.0)); }
get { return (Mean/2.0) + Math.Log(2.0*SpecialFunctions.Gamma(Mean/2.0)) + ((1.0 - (Mean/2.0))*SpecialFunctions.DiGamma(Mean/2.0)); }
}
/// <summary>
@ -160,7 +168,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Skewness
{
get { return Math.Sqrt(8.0 / Mean); }
get { return Math.Sqrt(8.0/Mean); }
}
/// <summary>
@ -170,7 +178,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
return SpecialFunctions.GammaLowerIncomplete(Mean / 2.0, x / 2.0) / SpecialFunctions.Gamma(Mean / 2.0);
return SpecialFunctions.GammaLowerIncomplete(Mean/2.0, x/2.0)/SpecialFunctions.Gamma(Mean/2.0);
}
#endregion
@ -190,7 +198,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Median
{
get { return Mean - (2.0 / 3.0); }
get { return Mean - (2.0/3.0); }
}
/// <summary>
@ -216,7 +224,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the density at <paramref name="x"/>.</returns>
public double Density(double x)
{
return (Math.Pow(x, (Mean / 2.0) - 1.0) * Math.Exp(-x / 2.0)) / (Math.Pow(2.0, Mean / 2.0) * SpecialFunctions.Gamma(Mean / 2.0));
return (Math.Pow(x, (Mean/2.0) - 1.0)*Math.Exp(-x/2.0))/(Math.Pow(2.0, Mean/2.0)*SpecialFunctions.Gamma(Mean/2.0));
}
/// <summary>
@ -226,7 +234,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the log density at <paramref name="x"/>.</returns>
public double DensityLn(double x)
{
return (-x / 2.0) + (((Mean / 2.0) - 1.0) * Math.Log(x)) - ((Mean / 2.0) * Math.Log(2)) - SpecialFunctions.GammaLn(Mean / 2.0);
return (-x/2.0) + (((Mean/2.0) - 1.0)*Math.Log(x)) - ((Mean/2.0)*Math.Log(2)) - SpecialFunctions.GammaLn(Mean/2.0);
}
#endregion
@ -243,7 +251,7 @@ namespace MathNet.Numerics.Distributions
if (Math.Floor(dof) == dof && dof < Int32.MaxValue)
{
double sum = 0;
var n = (int)dof;
var n = (int) dof;
for (var i = 0; i < n; i++)
{
sum += Math.Pow(Normal.Sample(rnd, 0.0, 1.0), 2);
@ -252,7 +260,7 @@ namespace MathNet.Numerics.Distributions
}
//Call the gamma function (see http://en.wikipedia.org/wiki/Gamma_distribution#Specializations
//for a justification)
return Gamma.SampleUnchecked(rnd, dof / 2.0, .5);
return Gamma.SampleUnchecked(rnd, dof/2.0, .5);
}
/// <summary>

39
src/Numerics/Distributions/Continuous/ContinuousUniform.cs

@ -63,8 +63,7 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the ContinuousUniform class with lower bound 0 and upper bound 1.
/// </summary>
public ContinuousUniform()
: this(0.0, 1.0)
public ContinuousUniform() : this(0.0, 1.0)
{
}
@ -76,8 +75,21 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="ArgumentException">If the upper bound is smaller than the lower bound.</exception>
public ContinuousUniform(double lower, double upper)
{
_random = new Random();
SetParameters(lower, upper);
}
/// <summary>
/// Initializes a new instance of the ContinuousUniform class with given lower and upper bounds.
/// </summary>
/// <param name="lower">Lower bound.</param>
/// <param name="upper">Upper bound; must be at least as large as lower.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentException">If the upper bound is smaller than the lower bound.</exception>
public ContinuousUniform(double lower, double upper, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(lower, upper);
RandomSource = new Random();
}
/// <summary>
@ -133,7 +145,6 @@ namespace MathNet.Numerics.Distributions
public double Lower
{
get { return _lower; }
set { SetParameters(value, _upper); }
}
@ -143,7 +154,6 @@ namespace MathNet.Numerics.Distributions
public double Upper
{
get { return _upper; }
set { SetParameters(_lower, value); }
}
@ -155,7 +165,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -172,7 +181,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return (_lower + _upper) / 2.0; }
get { return (_lower + _upper)/2.0; }
}
/// <summary>
@ -180,7 +189,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return (_upper - _lower) * (_upper - _lower) / 12.0; }
get { return (_upper - _lower)*(_upper - _lower)/12.0; }
}
/// <summary>
@ -188,7 +197,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return (_upper - _lower) / Math.Sqrt(12.0); }
get { return (_upper - _lower)/Math.Sqrt(12.0); }
}
/// <summary>
@ -218,7 +227,7 @@ namespace MathNet.Numerics.Distributions
/// <value></value>
public double Mode
{
get { return (_lower + _upper) / 2.0; }
get { return (_lower + _upper)/2.0; }
}
/// <summary>
@ -227,7 +236,7 @@ namespace MathNet.Numerics.Distributions
/// <value></value>
public double Median
{
get { return (_lower + _upper) / 2.0; }
get { return (_lower + _upper)/2.0; }
}
/// <summary>
@ -255,7 +264,7 @@ namespace MathNet.Numerics.Distributions
{
if (x >= _lower && x <= _upper)
{
return 1.0 / (_upper - _lower);
return 1.0/(_upper - _lower);
}
return 0.0;
@ -293,7 +302,7 @@ namespace MathNet.Numerics.Distributions
return 1.0;
}
return (x - _lower) / (_upper - _lower);
return (x - _lower)/(_upper - _lower);
}
#endregion
@ -307,7 +316,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a uniformly distributed random number.</returns>
internal static double SampleUnchecked(Random rnd, double lower, double upper)
{
return lower + (rnd.NextDouble() * (upper - lower));
return lower + (rnd.NextDouble()*(upper - lower));
}
/// <summary>
@ -368,4 +377,4 @@ namespace MathNet.Numerics.Distributions
}
}
}
}
}

78
src/Numerics/Distributions/Continuous/Erlang.cs

@ -61,16 +61,24 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="Erlang"/> class.
/// </summary>
/// <param name="shape">
/// The shape of the Erlang distribution.
/// </param>
/// <param name="invScale">
/// The inverse scale of the Erlang distribution.
/// </param>
/// <param name="shape">The shape of the Erlang distribution.</param>
/// <param name="invScale">The inverse scale of the Erlang distribution.</param>
public Erlang(int shape, double invScale)
{
_random = new Random();
SetParameters(shape, invScale);
}
/// <summary>
/// Initializes a new instance of the <see cref="Erlang"/> class.
/// </summary>
/// <param name="shape">The shape of the Erlang distribution.</param>
/// <param name="invScale">The inverse scale of the Erlang distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Erlang(int shape, double invScale, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(shape, invScale);
RandomSource = new Random();
}
/// <summary>
@ -82,7 +90,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a normal distribution.</returns>
public static Erlang WithShapeScale(int shape, double scale)
{
return new Erlang(shape, 1.0 / scale);
return new Erlang(shape, 1.0/scale);
}
/// <summary>
@ -134,8 +142,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int Shape
{
get { return (int)_shape; }
get { return (int) _shape; }
set { SetParameters(value, _invScale); }
}
@ -144,11 +151,10 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Scale
{
get { return 1.0 / _invScale; }
get { return 1.0/_invScale; }
set
{
var invScale = 1.0 / value;
var invScale = 1.0/value;
if (Double.IsNegativeInfinity(invScale))
{
@ -165,7 +171,6 @@ namespace MathNet.Numerics.Distributions
public double InvScale
{
get { return _invScale; }
set { SetParameters(_shape, value); }
}
@ -186,7 +191,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -215,7 +219,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return _shape / _invScale;
return _shape/_invScale;
}
}
@ -236,7 +240,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return _shape / (_invScale * _invScale);
return _shape/(_invScale*_invScale);
}
}
@ -257,7 +261,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return Math.Sqrt(_shape) / _invScale;
return Math.Sqrt(_shape)/_invScale;
}
}
@ -278,7 +282,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return _shape - Math.Log(_invScale) + SpecialFunctions.GammaLn(_shape) + ((1.0 - _shape) * SpecialFunctions.DiGamma(_shape));
return _shape - Math.Log(_invScale) + SpecialFunctions.GammaLn(_shape) + ((1.0 - _shape)*SpecialFunctions.DiGamma(_shape));
}
}
@ -299,7 +303,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return 2.0 / Math.Sqrt(_shape);
return 2.0/Math.Sqrt(_shape);
}
}
@ -320,7 +324,7 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
return SpecialFunctions.GammaLowerRegularized(_shape, x * _invScale);
return SpecialFunctions.GammaLowerRegularized(_shape, x*_invScale);
}
#endregion
@ -349,7 +353,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return (_shape - 1.0) / _invScale;
return (_shape - 1.0)/_invScale;
}
}
@ -396,10 +400,10 @@ namespace MathNet.Numerics.Distributions
if (_shape == 1.0)
{
return _invScale * Math.Exp(-_invScale * x);
return _invScale*Math.Exp(-_invScale*x);
}
return Math.Pow(_invScale, _shape) * Math.Pow(x, _shape - 1.0) * Math.Exp(-_invScale * x) / SpecialFunctions.Gamma(_shape);
return Math.Pow(_invScale, _shape)*Math.Pow(x, _shape - 1.0)*Math.Exp(-_invScale*x)/SpecialFunctions.Gamma(_shape);
}
/// <summary>
@ -421,10 +425,10 @@ namespace MathNet.Numerics.Distributions
if (_shape == 1.0)
{
return Math.Log(_invScale) - (_invScale * x);
return Math.Log(_invScale) - (_invScale*x);
}
return (_shape * Math.Log(_invScale)) + ((_shape - 1.0) * Math.Log(x)) - (_invScale * x) - SpecialFunctions.GammaLn(_shape);
return (_shape*Math.Log(_invScale)) + ((_shape - 1.0)*Math.Log(x)) - (_invScale*x) - SpecialFunctions.GammaLn(_shape);
}
#endregion
@ -453,32 +457,32 @@ namespace MathNet.Numerics.Distributions
if (shape < 1.0)
{
a = shape + 1.0;
alphafix = Math.Pow(rnd.NextDouble(), 1.0 / shape);
alphafix = Math.Pow(rnd.NextDouble(), 1.0/shape);
}
var d = a - (1.0 / 3.0);
var c = 1.0 / Math.Sqrt(9.0 * d);
var d = a - (1.0/3.0);
var c = 1.0/Math.Sqrt(9.0*d);
while (true)
{
var x = Normal.Sample(rnd, 0.0, 1.0);
var v = 1.0 + (c * x);
var v = 1.0 + (c*x);
while (v <= 0.0)
{
x = Normal.Sample(rnd, 0.0, 1.0);
v = 1.0 + (c * x);
v = 1.0 + (c*x);
}
v = v * v * v;
v = v*v*v;
var u = rnd.NextDouble();
x = x * x;
if (u < 1.0 - (0.0331 * x * x))
x = x*x;
if (u < 1.0 - (0.0331*x*x))
{
return alphafix * d * v / invScale;
return alphafix*d*v/invScale;
}
if (Math.Log(u) < (0.5 * x) + (d * (1.0 - v + Math.Log(v))))
if (Math.Log(u) < (0.5*x) + (d*(1.0 - v + Math.Log(v))))
{
return alphafix * d * v / invScale;
return alphafix*d*v/invScale;
}
}
}

35
src/Numerics/Distributions/Continuous/Exponential.cs

@ -54,13 +54,22 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="Exponential"/> class.
/// </summary>
/// <param name="lambda">
/// The lambda parameter of the Exponential distribution.
/// </param>
/// <param name="lambda">The lambda parameter of the Exponential distribution.</param>
public Exponential(double lambda)
{
_random = new Random();
SetParameters(lambda);
}
/// <summary>
/// Initializes a new instance of the <see cref="Exponential"/> class.
/// </summary>
/// <param name="lambda">The lambda parameter of the Exponential distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Exponential(double lambda, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(lambda);
RandomSource = new Random();
}
/// <summary>
@ -104,7 +113,6 @@ namespace MathNet.Numerics.Distributions
public double Lambda
{
get { return _lambda; }
set { SetParameters(value); }
}
@ -125,7 +133,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -142,7 +149,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return 1.0 / _lambda; }
get { return 1.0/_lambda; }
}
/// <summary>
@ -150,7 +157,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return 1.0 / (_lambda * _lambda); }
get { return 1.0/(_lambda*_lambda); }
}
/// <summary>
@ -158,7 +165,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return 1.0 / _lambda; }
get { return 1.0/_lambda; }
}
/// <summary>
@ -186,7 +193,7 @@ namespace MathNet.Numerics.Distributions
{
if (x >= 0.0)
{
return 1.0 - Math.Exp(-_lambda * x);
return 1.0 - Math.Exp(-_lambda*x);
}
return 0.0;
@ -209,7 +216,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Median
{
get { return Math.Log(2.0) / _lambda; }
get { return Math.Log(2.0)/_lambda; }
}
/// <summary>
@ -237,7 +244,7 @@ namespace MathNet.Numerics.Distributions
{
if (x >= 0.0)
{
return _lambda * Math.Exp(-_lambda * x);
return _lambda*Math.Exp(-_lambda*x);
}
return 0.0;
@ -250,7 +257,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the log density at <paramref name="x"/>.</returns>
public double DensityLn(double x)
{
return Math.Log(_lambda) - (_lambda * x);
return Math.Log(_lambda) - (_lambda*x);
}
#endregion
@ -269,7 +276,7 @@ namespace MathNet.Numerics.Distributions
r = rnd.NextDouble();
}
return -Math.Log(r) / lambda;
return -Math.Log(r)/lambda;
}
/// <summary>

41
src/Numerics/Distributions/Continuous/FisherSnedecor.cs

@ -59,16 +59,24 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="FisherSnedecor"/> class.
/// </summary>
/// <param name="d1">
/// The first parameter - degree of freedom.
/// </param>
/// <param name="d2">
/// The second parameter - degree of freedom.
/// </param>
/// <param name="d1">The first parameter - degree of freedom.</param>
/// <param name="d2">The second parameter - degree of freedom.</param>
public FisherSnedecor(double d1, double d2)
{
_random = new Random();
SetParameters(d1, d2);
}
/// <summary>
/// Initializes a new instance of the <see cref="FisherSnedecor"/> class.
/// </summary>
/// <param name="d1">The first parameter - degree of freedom.</param>
/// <param name="d2">The second parameter - degree of freedom.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public FisherSnedecor(double d1, double d2, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(d1, d2);
RandomSource = new Random();
}
/// <summary>
@ -114,7 +122,6 @@ namespace MathNet.Numerics.Distributions
public double DegreeOfFreedom1
{
get { return _d1; }
set { SetParameters(value, _d2); }
}
@ -124,7 +131,6 @@ namespace MathNet.Numerics.Distributions
public double DegreeOfFreedom2
{
get { return _d2; }
set { SetParameters(_d1, value); }
}
@ -145,12 +151,11 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
{
throw new ArgumentNullException(Resources.InvalidDistributionParameters);
throw new ArgumentNullException();
}
_random = value;
@ -169,7 +174,7 @@ namespace MathNet.Numerics.Distributions
throw new NotSupportedException();
}
return _d2 / (_d2 - 2.0);
return _d2/(_d2 - 2.0);
}
}
@ -185,7 +190,7 @@ namespace MathNet.Numerics.Distributions
throw new NotSupportedException();
}
return (2.0 * _d2 * _d2 * (_d1 + _d2 - 2.0)) / (_d1 * (_d2 - 2.0) * (_d2 - 2.0) * (_d2 - 4.0));
return (2.0*_d2*_d2*(_d1 + _d2 - 2.0))/(_d1*(_d2 - 2.0)*(_d2 - 2.0)*(_d2 - 4.0));
}
}
@ -217,7 +222,7 @@ namespace MathNet.Numerics.Distributions
throw new NotSupportedException();
}
return (((2.0 * _d1) + _d2 - 2.0) * Math.Sqrt(8.0 * (_d2 - 4.0))) / ((_d2 - 6.0) * Math.Sqrt(_d1 * (_d1 + _d2 - 2.0)));
return (((2.0*_d1) + _d2 - 2.0)*Math.Sqrt(8.0*(_d2 - 4.0)))/((_d2 - 6.0)*Math.Sqrt(_d1*(_d1 + _d2 - 2.0)));
}
}
@ -228,7 +233,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
return SpecialFunctions.BetaRegularized(_d1 / 2.0, _d2 / 2.0, _d1 * x / ((_d1 * x) + _d2));
return SpecialFunctions.BetaRegularized(_d1/2.0, _d2/2.0, _d1*x/((_d1*x) + _d2));
}
#endregion
@ -247,7 +252,7 @@ namespace MathNet.Numerics.Distributions
throw new NotSupportedException();
}
return (_d2 * (_d1 - 2.0)) / (_d1 * (_d2 + 2.0));
return (_d2*(_d1 - 2.0))/(_d1*(_d2 + 2.0));
}
}
@ -282,7 +287,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the density at <paramref name="x"/>.</returns>
public double Density(double x)
{
return Math.Sqrt(Math.Pow(_d1 * x, _d1) * Math.Pow(_d2, _d2) / Math.Pow((_d1 * x) + _d2, _d1 + _d2)) / (x * SpecialFunctions.Beta(_d1 / 2.0, _d2 / 2.0));
return Math.Sqrt(Math.Pow(_d1*x, _d1)*Math.Pow(_d2, _d2)/Math.Pow((_d1*x) + _d2, _d1 + _d2))/(x*SpecialFunctions.Beta(_d1/2.0, _d2/2.0));
}
/// <summary>
@ -306,7 +311,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a <c>FisherSnedecor</c> distributed random number.</returns>
internal static double SampleUnchecked(Random rnd, double d1, double d2)
{
return (ChiSquare.Sample(rnd, d1) / d1) / (ChiSquare.Sample(rnd, d2) / d2);
return (ChiSquare.Sample(rnd, d1)/d1)/(ChiSquare.Sample(rnd, d2)/d2);
}
/// <summary>

68
src/Numerics/Distributions/Continuous/Gamma.cs

@ -71,8 +71,20 @@ namespace MathNet.Numerics.Distributions
/// <param name="invScale">The inverse scale of the Gamma distribution.</param>
public Gamma(double shape, double invScale)
{
_random = new Random();
SetParameters(shape, invScale);
}
/// <summary>
/// Initializes a new instance of the Gamma class.
/// </summary>
/// <param name="shape">The shape of the Gamma distribution.</param>
/// <param name="invScale">The inverse scale of the Gamma distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Gamma(double shape, double invScale, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(shape, invScale);
RandomSource = new Random();
}
/// <summary>
@ -84,7 +96,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a normal distribution.</returns>
public static Gamma WithShapeScale(double shape, double scale)
{
return new Gamma(shape, 1.0 / scale);
return new Gamma(shape, 1.0/scale);
}
/// <summary>
@ -147,7 +159,6 @@ namespace MathNet.Numerics.Distributions
public double Shape
{
get { return _shape; }
set { SetParameters(value, _invScale); }
}
@ -156,11 +167,10 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Scale
{
get { return 1.0 / _invScale; }
get { return 1.0/_invScale; }
set
{
var invScale = 1.0 / value;
var invScale = 1.0/value;
if (Double.IsNegativeInfinity(invScale))
{
@ -177,7 +187,6 @@ namespace MathNet.Numerics.Distributions
public double InvScale
{
get { return _invScale; }
set { SetParameters(_shape, value); }
}
@ -189,7 +198,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -218,7 +226,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return _shape / _invScale;
return _shape/_invScale;
}
}
@ -239,7 +247,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return _shape / (_invScale * _invScale);
return _shape/(_invScale*_invScale);
}
}
@ -260,7 +268,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return Math.Sqrt(_shape / (_invScale * _invScale));
return Math.Sqrt(_shape/(_invScale*_invScale));
}
}
@ -281,7 +289,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return _shape - Math.Log(_invScale) + SpecialFunctions.GammaLn(_shape) + ((1.0 - _shape) * SpecialFunctions.DiGamma(_shape));
return _shape - Math.Log(_invScale) + SpecialFunctions.GammaLn(_shape) + ((1.0 - _shape)*SpecialFunctions.DiGamma(_shape));
}
}
@ -302,7 +310,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return 2.0 / Math.Sqrt(_shape);
return 2.0/Math.Sqrt(_shape);
}
}
@ -327,7 +335,7 @@ namespace MathNet.Numerics.Distributions
return Double.NaN;
}
return (_shape - 1.0) / _invScale;
return (_shape - 1.0)/_invScale;
}
}
@ -374,10 +382,10 @@ namespace MathNet.Numerics.Distributions
if (_shape == 1.0)
{
return _invScale * Math.Exp(-_invScale * x);
return _invScale*Math.Exp(-_invScale*x);
}
return Math.Pow(_invScale, _shape) * Math.Pow(x, _shape - 1.0) * Math.Exp(-_invScale * x) / SpecialFunctions.Gamma(_shape);
return Math.Pow(_invScale, _shape)*Math.Pow(x, _shape - 1.0)*Math.Exp(-_invScale*x)/SpecialFunctions.Gamma(_shape);
}
/// <summary>
@ -399,10 +407,10 @@ namespace MathNet.Numerics.Distributions
if (_shape == 1.0)
{
return Math.Log(_invScale) - (_invScale * x);
return Math.Log(_invScale) - (_invScale*x);
}
return (_shape * Math.Log(_invScale)) + ((_shape - 1.0) * Math.Log(x)) - (_invScale * x) - SpecialFunctions.GammaLn(_shape);
return (_shape*Math.Log(_invScale)) + ((_shape - 1.0)*Math.Log(x)) - (_invScale*x) - SpecialFunctions.GammaLn(_shape);
}
/// <summary>
@ -422,7 +430,7 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
return SpecialFunctions.GammaLowerRegularized(_shape, x * _invScale);
return SpecialFunctions.GammaLowerRegularized(_shape, x*_invScale);
}
#endregion
@ -451,32 +459,32 @@ namespace MathNet.Numerics.Distributions
if (shape < 1.0)
{
a = shape + 1.0;
alphafix = Math.Pow(rnd.NextDouble(), 1.0 / shape);
alphafix = Math.Pow(rnd.NextDouble(), 1.0/shape);
}
var d = a - (1.0 / 3.0);
var c = 1.0 / Math.Sqrt(9.0 * d);
var d = a - (1.0/3.0);
var c = 1.0/Math.Sqrt(9.0*d);
while (true)
{
var x = Normal.Sample(rnd, 0.0, 1.0);
var v = 1.0 + (c * x);
var v = 1.0 + (c*x);
while (v <= 0.0)
{
x = Normal.Sample(rnd, 0.0, 1.0);
v = 1.0 + (c * x);
v = 1.0 + (c*x);
}
v = v * v * v;
v = v*v*v;
var u = rnd.NextDouble();
x = x * x;
if (u < 1.0 - (0.0331 * x * x))
x = x*x;
if (u < 1.0 - (0.0331*x*x))
{
return alphafix * d * v / invScale;
return alphafix*d*v/invScale;
}
if (Math.Log(u) < (0.5 * x) + (d * (1.0 - v + Math.Log(v))))
if (Math.Log(u) < (0.5*x) + (d*(1.0 - v + Math.Log(v))))
{
return alphafix * d * v / invScale;
return alphafix*d*v/invScale;
}
}
}

43
src/Numerics/Distributions/Continuous/InverseGamma.cs

@ -60,16 +60,24 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="InverseGamma"/> class.
/// </summary>
/// <param name="shape">
/// The shape (alpha) parameter of the inverse Gamma distribution.
/// </param>
/// <param name="scale">
/// The scale (beta) parameter of the inverse Gamma distribution.
/// </param>
/// <param name="shape">The shape (alpha) parameter of the inverse Gamma distribution.</param>
/// <param name="scale">The scale (beta) parameter of the inverse Gamma distribution.</param>
public InverseGamma(double shape, double scale)
{
SetParameters(shape, scale);
_random = new Random();
SetParameters(shape, scale);
}
/// <summary>
/// Initializes a new instance of the <see cref="InverseGamma"/> class.
/// </summary>
/// <param name="shape">The shape (alpha) parameter of the inverse Gamma distribution.</param>
/// <param name="scale">The scale (beta) parameter of the inverse Gamma distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public InverseGamma(double shape, double scale, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(shape, scale);
}
/// <summary>
@ -124,7 +132,6 @@ namespace MathNet.Numerics.Distributions
public double Shape
{
get { return _shape; }
set { SetParameters(value, _scale); }
}
@ -134,7 +141,6 @@ namespace MathNet.Numerics.Distributions
public double Scale
{
get { return _scale; }
set { SetParameters(_shape, value); }
}
@ -155,7 +161,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -179,7 +184,7 @@ namespace MathNet.Numerics.Distributions
throw new NotSupportedException();
}
return _scale / (_shape - 1.0);
return _scale/(_shape - 1.0);
}
}
@ -195,7 +200,7 @@ namespace MathNet.Numerics.Distributions
throw new NotSupportedException();
}
return _scale * _scale / ((_shape - 1.0) * (_shape - 1.0) * (_shape - 2.0));
return _scale*_scale/((_shape - 1.0)*(_shape - 1.0)*(_shape - 2.0));
}
}
@ -204,7 +209,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return _scale / (Math.Abs(_shape - 1.0) * Math.Sqrt(_shape - 2.0)); }
get { return _scale/(Math.Abs(_shape - 1.0)*Math.Sqrt(_shape - 2.0)); }
}
/// <summary>
@ -212,7 +217,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Entropy
{
get { return _shape + Math.Log(_scale) + SpecialFunctions.GammaLn(_shape) - ((1 + _shape) * SpecialFunctions.DiGamma(_shape)); }
get { return _shape + Math.Log(_scale) + SpecialFunctions.GammaLn(_shape) - ((1 + _shape)*SpecialFunctions.DiGamma(_shape)); }
}
/// <summary>
@ -227,7 +232,7 @@ namespace MathNet.Numerics.Distributions
throw new NotSupportedException();
}
return (4 * Math.Sqrt(_shape - 2)) / (_shape - 3);
return (4*Math.Sqrt(_shape - 2))/(_shape - 3);
}
}
@ -238,7 +243,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
return SpecialFunctions.GammaUpperRegularized(_shape, _scale / x);
return SpecialFunctions.GammaUpperRegularized(_shape, _scale/x);
}
#endregion
@ -250,7 +255,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mode
{
get { return _scale / (_shape + 1.0); }
get { return _scale/(_shape + 1.0); }
}
/// <summary>
@ -287,7 +292,7 @@ namespace MathNet.Numerics.Distributions
{
if (x >= 0.0)
{
return Math.Pow(_scale, _shape) * Math.Pow(x, -_shape - 1.0) * Math.Exp(-_scale / x) / SpecialFunctions.Gamma(_shape);
return Math.Pow(_scale, _shape)*Math.Pow(x, -_shape - 1.0)*Math.Exp(-_scale/x)/SpecialFunctions.Gamma(_shape);
}
return 0.0;
@ -314,7 +319,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a random number from the distribution.</returns>
internal static double SampleUnchecked(Random rnd, double shape, double scale)
{
return 1.0 / Gamma.Sample(rnd, shape, scale);
return 1.0/Gamma.Sample(rnd, shape, scale);
}
/// <summary>

42
src/Numerics/Distributions/Continuous/Laplace.cs

@ -59,7 +59,6 @@ namespace MathNet.Numerics.Distributions
public double Location
{
get { return Mean; }
set { SetParameters(value, _scale); }
}
@ -69,7 +68,6 @@ namespace MathNet.Numerics.Distributions
public double Scale
{
get { return _scale; }
set { SetParameters(Mean, value); }
}
@ -84,19 +82,26 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="Laplace"/> class.
/// </summary>
/// <param name="location">
/// The location for the Laplace distribution.
/// </param>
/// <param name="scale">
/// The scale for the Laplace distribution.
/// </param>
/// <exception cref="ArgumentException">
/// If <paramref name="scale"/> is negative.
/// </exception>
/// <param name="location">The location for the Laplace distribution.</param>
/// <param name="scale">The scale for the Laplace distribution.</param>
/// <exception cref="ArgumentException">If <paramref name="scale"/> is negative.</exception>
public Laplace(double location, double scale)
{
_random = new Random();
SetParameters(location, scale);
}
/// <summary>
/// Initializes a new instance of the <see cref="Laplace"/> class.
/// </summary>
/// <param name="location">The location for the Laplace distribution.</param>
/// <param name="scale">The scale for the Laplace distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentException">If <paramref name="scale"/> is negative.</exception>
public Laplace(double location, double scale, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(location, scale);
RandomSource = new Random();
}
/// <summary>
@ -154,7 +159,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -176,7 +180,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return 2.0 * _scale * _scale; }
get { return 2.0*_scale*_scale; }
}
/// <summary>
@ -184,7 +188,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return Math.Sqrt(2.0) * _scale; }
get { return Math.Sqrt(2.0)*_scale; }
}
/// <summary>
@ -192,7 +196,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Entropy
{
get { return Math.Log(2.0 * Constants.E * _scale); }
get { return Math.Log(2.0*Constants.E*_scale); }
}
/// <summary>
@ -210,7 +214,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
return 0.5 * (1.0 + (Math.Sign(x - Mean) * (1.0 - Math.Exp(-Math.Abs(x - Mean) / _scale))));
return 0.5*(1.0 + (Math.Sign(x - Mean)*(1.0 - Math.Exp(-Math.Abs(x - Mean)/_scale))));
}
#endregion
@ -256,7 +260,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the density at <paramref name="x"/>.</returns>
public double Density(double x)
{
return Math.Exp(-Math.Abs(x - Mean) / _scale) / (2.0 * _scale);
return Math.Exp(-Math.Abs(x - Mean)/_scale)/(2.0*_scale);
}
/// <summary>
@ -281,7 +285,7 @@ namespace MathNet.Numerics.Distributions
internal static double SampleUnchecked(Random rnd, double location, double scale)
{
var u = rnd.NextDouble() - 0.5;
return location - (scale * Math.Sign(u) * Math.Log(1.0 - (2.0 * Math.Abs(u))));
return location - (scale*Math.Sign(u)*Math.Log(1.0 - (2.0*Math.Abs(u))));
}
/// <summary>

90
src/Numerics/Distributions/Continuous/LogNormal.cs

@ -24,11 +24,14 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System.Linq;
using MathNet.Numerics.Properties;
using MathNet.Numerics.Statistics;
using System.Collections.Generic;
namespace MathNet.Numerics.Distributions
{
using System;
using System.Collections.Generic;
using Properties;
/// <summary>
/// Implements the univariate Log-Normal distribution. For details about this distribution, see
@ -61,16 +64,48 @@ namespace MathNet.Numerics.Distributions
/// The distribution will be initialized with the default <seealso cref="System.Random"/>
/// random number generator.
/// </summary>
/// <param name="mu">
/// The mu of the logarithm of the distribution.
/// </param>
/// <param name="sigma">
/// The standard deviation of the logarithm of the distribution.
/// </param>
/// <param name="mu">The mu of the logarithm of the distribution.</param>
/// <param name="sigma">The standard deviation of the logarithm of the distribution.</param>
public LogNormal(double mu, double sigma)
{
_random = new Random();
SetParameters(mu, sigma);
}
/// <summary>
/// Initializes a new instance of the <see cref="LogNormal"/> class.
/// The distribution will be initialized with the default <seealso cref="System.Random"/>
/// random number generator.
/// </summary>
/// <param name="mu">The mu of the logarithm of the distribution.</param>
/// <param name="sigma">The standard deviation of the logarithm of the distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public LogNormal(double mu, double sigma, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(mu, sigma);
RandomSource = new Random();
}
/// <summary>
/// Constructs a log-normal distribution with the desired mean and variance. The distribution will
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
/// </summary>
/// <param name="mean">The mean of the log-normal distribution.</param>
/// <param name="var">The variance of the log-normal distribution.</param>
/// <returns>a log-normal distribution.</returns>
public static LogNormal WithMeanVariance(double mean, double var)
{
var sigma2 = Math.Log(var / (mean * mean) + 1.0);
return new LogNormal(Math.Log(mean) - sigma2 / 2.0, Math.Sqrt(sigma2));
}
/// <summary>
/// Estimates the log-normal distribution parameters from sample data with maximum-likelihood.
/// </summary>
public static LogNormal Estimate(IEnumerable<double> samples)
{
var muSigma2 = samples.Select(s => Math.Log(s)).MeanVariance();
return new LogNormal(muSigma2.Item1, Math.Sqrt(muSigma2.Item2));
}
/// <summary>
@ -121,7 +156,6 @@ namespace MathNet.Numerics.Distributions
public double Mu
{
get { return _mu; }
set { SetParameters(value, _sigma); }
}
@ -131,7 +165,6 @@ namespace MathNet.Numerics.Distributions
public double Sigma
{
get { return _sigma; }
set { SetParameters(_mu, value); }
}
@ -143,7 +176,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -160,7 +192,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return Math.Exp(_mu + (_sigma * _sigma / 2.0)); }
get { return Math.Exp(_mu + (_sigma*_sigma/2.0)); }
}
/// <summary>
@ -170,8 +202,8 @@ namespace MathNet.Numerics.Distributions
{
get
{
var sigma2 = _sigma * _sigma;
return (Math.Exp(sigma2) - 1.0) * Math.Exp(_mu + _mu + sigma2);
var sigma2 = _sigma*_sigma;
return (Math.Exp(sigma2) - 1.0)*Math.Exp(_mu + _mu + sigma2);
}
}
@ -182,8 +214,8 @@ namespace MathNet.Numerics.Distributions
{
get
{
var sigma2 = _sigma * _sigma;
return Math.Sqrt((Math.Exp(sigma2) - 1.0) * Math.Exp(_mu + _mu + sigma2));
var sigma2 = _sigma*_sigma;
return Math.Sqrt((Math.Exp(sigma2) - 1.0)*Math.Exp(_mu + _mu + sigma2));
}
}
@ -202,8 +234,8 @@ namespace MathNet.Numerics.Distributions
{
get
{
var expsigma2 = Math.Exp(_sigma * _sigma);
return (expsigma2 + 2.0) * Math.Sqrt(expsigma2 - 1);
var expsigma2 = Math.Exp(_sigma*_sigma);
return (expsigma2 + 2.0)*Math.Sqrt(expsigma2 - 1);
}
}
@ -216,7 +248,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mode
{
get { return Math.Exp(_mu - (_sigma * _sigma)); }
get { return Math.Exp(_mu - (_sigma*_sigma)); }
}
/// <summary>
@ -255,8 +287,8 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
var a = (Math.Log(x) - _mu) / _sigma;
return Math.Exp(-0.5 * a * a) / (x * _sigma * Constants.Sqrt2Pi);
var a = (Math.Log(x) - _mu)/_sigma;
return Math.Exp(-0.5*a*a)/(x*_sigma*Constants.Sqrt2Pi);
}
/// <summary>
@ -271,8 +303,8 @@ namespace MathNet.Numerics.Distributions
return Double.NegativeInfinity;
}
var a = (Math.Log(x) - _mu) / _sigma;
return (-0.5 * a * a) - Math.Log(x * _sigma) - Constants.LogSqrt2Pi;
var a = (Math.Log(x) - _mu)/_sigma;
return (-0.5*a*a) - Math.Log(x*_sigma) - Constants.LogSqrt2Pi;
}
/// <summary>
@ -287,7 +319,7 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
return 0.5 * (1.0 + SpecialFunctions.Erf((Math.Log(x) - _mu) / (_sigma * Constants.Sqrt2)));
return 0.5*(1.0 + SpecialFunctions.Erf((Math.Log(x) - _mu)/(_sigma*Constants.Sqrt2)));
}
#endregion
@ -310,8 +342,8 @@ namespace MathNet.Numerics.Distributions
while (true)
{
var sample = Normal.SampleUncheckedBoxMuller(RandomSource);
yield return Math.Exp(_mu + (_sigma * sample.Item1));
yield return Math.Exp(_mu + (_sigma * sample.Item2));
yield return Math.Exp(_mu + (_sigma*sample.Item1));
yield return Math.Exp(_mu + (_sigma*sample.Item2));
}
}
@ -349,8 +381,8 @@ namespace MathNet.Numerics.Distributions
while (true)
{
var sample = Normal.SampleUncheckedBoxMuller(rng);
yield return Math.Exp(mu + (sigma * sample.Item1));
yield return Math.Exp(mu + (sigma * sample.Item2));
yield return Math.Exp(mu + (sigma*sample.Item1));
yield return Math.Exp(mu + (sigma*sample.Item2));
}
}
}

113
src/Numerics/Distributions/Continuous/Normal.cs

@ -24,11 +24,13 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.Properties;
using MathNet.Numerics.Statistics;
using System.Collections.Generic;
namespace MathNet.Numerics.Distributions
{
using System;
using System.Collections.Generic;
using Properties;
/// <summary>
/// Implements the univariate Normal (or Gaussian) distribution. For details about this distribution, see
@ -66,6 +68,17 @@ namespace MathNet.Numerics.Distributions
{
}
/// <summary>
/// Initializes a new instance of the Normal class. This is a normal distribution with mean 0.0
/// and standard deviation 1.0. The distribution will
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
/// </summary>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Normal(Random randomSource)
: this(0.0, 1.0, randomSource)
{
}
/// <summary>
/// Initializes a new instance of the Normal class with a particular mean and standard deviation. The distribution will
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
@ -74,8 +87,21 @@ namespace MathNet.Numerics.Distributions
/// <param name="stddev">The standard deviation of the normal distribution.</param>
public Normal(double mean, double stddev)
{
_random = new Random();
SetParameters(mean, stddev);
}
/// <summary>
/// Initializes a new instance of the Normal class with a particular mean and standard deviation. The distribution will
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
/// </summary>
/// <param name="mean">The mean of the normal distribution.</param>
/// <param name="stddev">The standard deviation of the normal distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Normal(double mean, double stddev, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(mean, stddev);
RandomSource = new Random();
}
/// <summary>
@ -111,7 +137,16 @@ namespace MathNet.Numerics.Distributions
/// <returns>a normal distribution.</returns>
public static Normal WithMeanPrecision(double mean, double precision)
{
return new Normal(mean, 1.0 / Math.Sqrt(precision));
return new Normal(mean, 1.0/Math.Sqrt(precision));
}
/// <summary>
/// Estimates the normal distribution parameters from sample data with maximum-likelihood.
/// </summary>
public static Normal Estimate(IEnumerable<double> samples)
{
var meanVariance = samples.MeanVariance();
return new Normal(meanVariance.Item1, Math.Sqrt(meanVariance.Item2));
}
/// <summary>
@ -161,11 +196,11 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Precision
{
get { return 1.0 / (_stdDev * _stdDev); }
get { return 1.0/(_stdDev*_stdDev); }
set
{
var sdev = 1.0 / Math.Sqrt(value);
var sdev = 1.0/Math.Sqrt(value);
// Handle the case when the precision is -0.
if (Double.IsInfinity(sdev))
@ -177,15 +212,12 @@ namespace MathNet.Numerics.Distributions
}
}
#region IDistribution implementation
/// <summary>
/// Gets or sets the random number generator which is used to draw random samples.
/// </summary>
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -203,7 +235,6 @@ namespace MathNet.Numerics.Distributions
public double Mean
{
get { return _mean; }
set { SetParameters(value, _stdDev); }
}
@ -212,8 +243,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return _stdDev * _stdDev; }
get { return _stdDev*_stdDev; }
set { SetParameters(_mean, Math.Sqrt(value)); }
}
@ -223,7 +253,6 @@ namespace MathNet.Numerics.Distributions
public double StdDev
{
get { return _stdDev; }
set { SetParameters(_mean, value); }
}
@ -243,10 +272,6 @@ namespace MathNet.Numerics.Distributions
get { return 0.0; }
}
#endregion
#region IContinuousDistribution implementation
/// <summary>
/// Gets the mode of the normal distribution.
/// </summary>
@ -280,7 +305,7 @@ namespace MathNet.Numerics.Distributions
}
/// <summary>
/// Computes the density of the normal distribution.
/// Computes the density of the normal distribution (PDF), i.e. dP(X &lt;= x)/dx.
/// </summary>
/// <param name="mean">The mean of the normal distribution.</param>
/// <param name="sdev">The standard deviation of the normal distribution.</param>
@ -288,12 +313,12 @@ namespace MathNet.Numerics.Distributions
/// <returns>the density at <paramref name="x"/>.</returns>
internal static double Density(double mean, double sdev, double x)
{
var d = (x - mean) / sdev;
return Math.Exp(-0.5 * d * d) / (Constants.Sqrt2Pi * sdev);
var d = (x - mean)/sdev;
return Math.Exp(-0.5*d*d)/(Constants.Sqrt2Pi*sdev);
}
/// <summary>
/// Computes the log density of the normal distribution.
/// Computes the log density of the normal distribution (lnPDF), i.e. ln(dP(X &lt;= x)/dx).
/// </summary>
/// <param name="mean">The mean of the normal distribution.</param>
/// <param name="sdev">The standard deviation of the normal distribution.</param>
@ -301,12 +326,12 @@ namespace MathNet.Numerics.Distributions
/// <returns>the log density at <paramref name="x"/>.</returns>
internal static double DensityLn(double mean, double sdev, double x)
{
var d = (x - mean) / sdev;
return (-0.5 * d * d) - Math.Log(sdev) - Constants.LogSqrt2Pi;
var d = (x - mean)/sdev;
return (-0.5*d*d) - Math.Log(sdev) - Constants.LogSqrt2Pi;
}
/// <summary>
/// Computes the density of the normal distribution.
/// Computes the density of the normal distribution (PDF), i.e. dP(X &lt;= x)/dx.
/// </summary>
/// <param name="x">The location at which to compute the density.</param>
/// <returns>the density at <paramref name="x"/>.</returns>
@ -316,7 +341,7 @@ namespace MathNet.Numerics.Distributions
}
/// <summary>
/// Computes the log density of the normal distribution.
/// Computes the log density of the normal distribution (lnPDF), i.e. ln(dP(X &lt;= x)/dx).
/// </summary>
/// <param name="x">The location at which to compute the log density.</param>
/// <returns>the log density at <paramref name="x"/>.</returns>
@ -326,7 +351,7 @@ namespace MathNet.Numerics.Distributions
}
/// <summary>
/// Computes the cumulative distribution function of the normal distribution.
/// Computes the cumulative distribution function (CDF) of the normal distribution, i.e. P(X &lt;= x).
/// </summary>
/// <param name="mean">The mean of the normal distribution.</param>
/// <param name="sdev">The standard deviation of the normal distribution.</param>
@ -334,11 +359,11 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
internal static double CumulativeDistribution(double mean, double sdev, double x)
{
return 0.5 * (1.0 + SpecialFunctions.Erf((x - mean) / (sdev * Constants.Sqrt2)));
return 0.5*(1.0 + SpecialFunctions.Erf((x - mean)/(sdev*Constants.Sqrt2)));
}
/// <summary>
/// Computes the cumulative distribution function of the normal distribution.
/// Computes the cumulative distribution function (CDF) of the normal distribution, i.e. P(X &lt;= x).
/// </summary>
/// <param name="x">The location at which to compute the cumulative density.</param>
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
@ -347,8 +372,6 @@ namespace MathNet.Numerics.Distributions
return CumulativeDistribution(_mean, _stdDev, x);
}
#endregion
/// <summary>
/// Computes the inverse cumulative distribution function of the normal distribution.
/// </summary>
@ -356,11 +379,9 @@ namespace MathNet.Numerics.Distributions
/// <returns>the inverse cumulative density at <paramref name="p"/>.</returns>
public double InverseCumulativeDistribution(double p)
{
return _mean - (_stdDev * Math.Sqrt(2.0) * SpecialFunctions.ErfcInv(2.0 * p));
return _mean - (_stdDev*Math.Sqrt(2.0)*SpecialFunctions.ErfcInv(2.0*p));
}
/// <summary>
/// Samples a pair of standard normal distributed random variables using the <i>Box-Muller</i> algorithm.
/// </summary>
@ -368,18 +389,18 @@ namespace MathNet.Numerics.Distributions
/// <returns>a pair of random numbers from the standard normal distribution.</returns>
internal static Tuple<double, double> SampleUncheckedBoxMuller(Random rnd)
{
var v1 = (2.0 * rnd.NextDouble()) - 1.0;
var v2 = (2.0 * rnd.NextDouble()) - 1.0;
var r = (v1 * v1) + (v2 * v2);
var v1 = (2.0*rnd.NextDouble()) - 1.0;
var v2 = (2.0*rnd.NextDouble()) - 1.0;
var r = (v1*v1) + (v2*v2);
while (r >= 1.0 || r == 0.0)
{
v1 = (2.0 * rnd.NextDouble()) - 1.0;
v2 = (2.0 * rnd.NextDouble()) - 1.0;
r = (v1 * v1) + (v2 * v2);
v1 = (2.0*rnd.NextDouble()) - 1.0;
v2 = (2.0*rnd.NextDouble()) - 1.0;
r = (v1*v1) + (v2*v2);
}
var fac = Math.Sqrt(-2.0 * Math.Log(r) / r);
return new Tuple<double, double>(v1 * fac, v2 * fac);
var fac = Math.Sqrt(-2.0*Math.Log(r)/r);
return new Tuple<double, double>(v1*fac, v2*fac);
}
/// <summary>
@ -391,7 +412,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a random number from the distribution.</returns>
internal static double SampleUnchecked(Random rnd, double mean, double stddev)
{
return mean + (stddev * SampleUncheckedBoxMuller(rnd).Item1);
return mean + (stddev*SampleUncheckedBoxMuller(rnd).Item1);
}
/// <summary>
@ -412,8 +433,8 @@ namespace MathNet.Numerics.Distributions
while (true)
{
var sample = SampleUncheckedBoxMuller(RandomSource);
yield return _mean + (_stdDev * sample.Item1);
yield return _mean + (_stdDev * sample.Item2);
yield return _mean + (_stdDev*sample.Item1);
yield return _mean + (_stdDev*sample.Item2);
}
}
@ -451,8 +472,8 @@ namespace MathNet.Numerics.Distributions
while (true)
{
var sample = SampleUncheckedBoxMuller(rnd);
yield return mean + (stddev * sample.Item1);
yield return mean + (stddev * sample.Item2);
yield return mean + (stddev*sample.Item1);
yield return mean + (stddev*sample.Item2);
}
}
}

48
src/Numerics/Distributions/Continuous/Pareto.cs

@ -61,19 +61,26 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="Pareto"/> class.
/// </summary>
/// <param name="scale">
/// The scale parameter of the distribution.
/// </param>
/// <param name="shape">
/// The shape parameter of the distribution.
/// </param>
/// <exception cref="ArgumentException">
/// If <paramref name="scale"/> or <paramref name="shape"/> are negative.
/// </exception>
/// <param name="scale">The scale parameter of the distribution.</param>
/// <param name="shape">The shape parameter of the distribution.</param>
/// <exception cref="ArgumentException">If <paramref name="scale"/> or <paramref name="shape"/> are negative.</exception>
public Pareto(double scale, double shape)
{
_random = new Random();
SetParameters(scale, shape);
}
/// <summary>
/// Initializes a new instance of the <see cref="Pareto"/> class.
/// </summary>
/// <param name="scale">The scale parameter of the distribution.</param>
/// <param name="shape">The shape parameter of the distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentException">If <paramref name="scale"/> or <paramref name="shape"/> are negative.</exception>
public Pareto(double scale, double shape, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(scale, shape);
RandomSource = new Random();
}
/// <summary>
@ -120,7 +127,6 @@ namespace MathNet.Numerics.Distributions
public double Scale
{
get { return _scale; }
set { SetParameters(value, _shape); }
}
@ -130,7 +136,6 @@ namespace MathNet.Numerics.Distributions
public double Shape
{
get { return _shape; }
set { SetParameters(_scale, value); }
}
@ -151,7 +156,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -175,7 +179,7 @@ namespace MathNet.Numerics.Distributions
throw new NotSupportedException();
}
return _shape * _scale / (_shape - 1.0);
return _shape*_scale/(_shape - 1.0);
}
}
@ -191,7 +195,7 @@ namespace MathNet.Numerics.Distributions
return double.PositiveInfinity;
}
return _scale * _scale * _shape / ((_shape - 1.0) * (_shape - 1.0) * (_shape - 2.0));
return _scale*_scale*_shape/((_shape - 1.0)*(_shape - 1.0)*(_shape - 2.0));
}
}
@ -200,7 +204,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return (_scale * Math.Sqrt(_shape)) / (Math.Abs(_shape - 1.0) * Math.Sqrt(_shape - 2.0)); }
get { return (_scale*Math.Sqrt(_shape))/(Math.Abs(_shape - 1.0)*Math.Sqrt(_shape - 2.0)); }
}
/// <summary>
@ -208,7 +212,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Entropy
{
get { return Math.Log(_shape / _scale) - (1.0 / _shape) - 1.0; }
get { return Math.Log(_shape/_scale) - (1.0/_shape) - 1.0; }
}
/// <summary>
@ -216,7 +220,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Skewness
{
get { return (2.0 * (_shape + 1.0) / (_shape - 3.0)) * Math.Sqrt((_shape - 2.0) / _shape); }
get { return (2.0*(_shape + 1.0)/(_shape - 3.0))*Math.Sqrt((_shape - 2.0)/_shape); }
}
/// <summary>
@ -226,7 +230,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
return 1.0 - Math.Pow(_scale / x, _shape);
return 1.0 - Math.Pow(_scale/x, _shape);
}
#endregion
@ -246,7 +250,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Median
{
get { return _scale * Math.Pow(2.0, 1.0 / _shape); }
get { return _scale*Math.Pow(2.0, 1.0/_shape); }
}
/// <summary>
@ -272,7 +276,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the density at <paramref name="x"/>.</returns>
public double Density(double x)
{
return _shape * Math.Pow(_scale, _shape) / Math.Pow(x, _shape + 1.0);
return _shape*Math.Pow(_scale, _shape)/Math.Pow(x, _shape + 1.0);
}
/// <summary>
@ -296,7 +300,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a random number from the Pareto distribution.</returns>
internal static double SampleUnchecked(Random rnd, double scale, double shape)
{
return scale * Math.Pow(rnd.NextDouble(), -1.0 / shape);
return scale*Math.Pow(rnd.NextDouble(), -1.0/shape);
}
/// <summary>

44
src/Numerics/Distributions/Continuous/Rayleigh.cs

@ -57,16 +57,24 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="Rayleigh"/> class.
/// </summary>
/// <param name="scale">
/// The scale parameter of the distribution.
/// </param>
/// <exception cref="ArgumentException">
/// If <paramref name="scale"/> is negative.
/// </exception>
/// <param name="scale">The scale parameter of the distribution.</param>
/// <exception cref="ArgumentException">If <paramref name="scale"/> is negative.</exception>
public Rayleigh(double scale)
{
_random = new Random();
SetParameters(scale);
}
/// <summary>
/// Initializes a new instance of the <see cref="Rayleigh"/> class.
/// </summary>
/// <param name="scale">The scale parameter of the distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentException">If <paramref name="scale"/> is negative.</exception>
public Rayleigh(double scale, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(scale);
RandomSource = new Random();
}
/// <summary>
@ -110,7 +118,6 @@ namespace MathNet.Numerics.Distributions
public double Scale
{
get { return _scale; }
set { SetParameters(value); }
}
@ -131,7 +138,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -148,7 +154,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return _scale * Math.Sqrt(Constants.PiOver2); }
get { return _scale*Math.Sqrt(Constants.PiOver2); }
}
/// <summary>
@ -156,7 +162,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return (2.0 - Constants.PiOver2) * _scale * _scale; }
get { return (2.0 - Constants.PiOver2)*_scale*_scale; }
}
/// <summary>
@ -164,7 +170,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return Math.Sqrt(2.0 - Constants.PiOver2) * _scale; }
get { return Math.Sqrt(2.0 - Constants.PiOver2)*_scale; }
}
/// <summary>
@ -172,7 +178,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Entropy
{
get { return 1.0 + Math.Log(_scale / Math.Sqrt(2)) + (Constants.EulerMascheroni / 2.0); }
get { return 1.0 + Math.Log(_scale/Math.Sqrt(2)) + (Constants.EulerMascheroni/2.0); }
}
/// <summary>
@ -180,7 +186,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Skewness
{
get { return (2.0 * Math.Sqrt(Constants.Pi) * (Constants.Pi - 3.0)) / Math.Pow(4.0 - Constants.Pi, 1.5); }
get { return (2.0*Math.Sqrt(Constants.Pi)*(Constants.Pi - 3.0))/Math.Pow(4.0 - Constants.Pi, 1.5); }
}
/// <summary>
@ -190,7 +196,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
return 1.0 - Math.Exp(-x * x / (2.0 * _scale * _scale));
return 1.0 - Math.Exp(-x*x/(2.0*_scale*_scale));
}
#endregion
@ -210,7 +216,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Median
{
get { return _scale * Math.Sqrt(Math.Log(4.0)); }
get { return _scale*Math.Sqrt(Math.Log(4.0)); }
}
/// <summary>
@ -236,7 +242,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the density at <paramref name="x"/>.</returns>
public double Density(double x)
{
return (x / (_scale * _scale)) * Math.Exp(-x * x / (2.0 * _scale * _scale));
return (x/(_scale*_scale))*Math.Exp(-x*x/(2.0*_scale*_scale));
}
/// <summary>
@ -246,7 +252,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the log density at <paramref name="x"/>.</returns>
public double DensityLn(double x)
{
return Math.Log(x / (_scale * _scale)) - (x * x / (2.0 * _scale * _scale));
return Math.Log(x/(_scale*_scale)) - (x*x/(2.0*_scale*_scale));
}
#endregion
@ -259,7 +265,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a random number from the Rayleigh distribution.</returns>
internal static double SampleUnchecked(Random rnd, double scale)
{
return scale * Math.Sqrt(-2.0 * Math.Log(rnd.NextDouble()));
return scale*Math.Sqrt(-2.0*Math.Log(rnd.NextDouble()));
}
/// <summary>

69
src/Numerics/Distributions/Continuous/Stable.cs

@ -72,22 +72,28 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="Stable"/> class.
/// </summary>
/// <param name="alpha">
/// The stability parameter of the distribution.
/// </param>
/// <param name="beta">
/// The skewness parameter of the distribution.
/// </param>
/// <param name="scale">
/// The scale parameter of the distribution.
/// </param>
/// <param name="location">
/// The location parameter of the distribution.
/// </param>
/// <param name="alpha">The stability parameter of the distribution.</param>
/// <param name="beta">The skewness parameter of the distribution.</param>
/// <param name="scale">The scale parameter of the distribution.</param>
/// <param name="location">The location parameter of the distribution.</param>
public Stable(double alpha, double beta, double scale, double location)
{
_random = new Random();
SetParameters(alpha, beta, scale, location);
}
/// <summary>
/// Initializes a new instance of the <see cref="Stable"/> class.
/// </summary>
/// <param name="alpha">The stability parameter of the distribution.</param>
/// <param name="beta">The skewness parameter of the distribution.</param>
/// <param name="scale">The scale parameter of the distribution.</param>
/// <param name="location">The location parameter of the distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Stable(double alpha, double beta, double scale, double location, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(alpha, beta, scale, location);
RandomSource = new Random();
}
/// <summary>
@ -149,7 +155,6 @@ namespace MathNet.Numerics.Distributions
public double Alpha
{
get { return _alpha; }
set { SetParameters(value, _beta, _scale, _location); }
}
@ -159,7 +164,6 @@ namespace MathNet.Numerics.Distributions
public double Beta
{
get { return _beta; }
set { SetParameters(_alpha, value, _scale, _location); }
}
@ -169,7 +173,6 @@ namespace MathNet.Numerics.Distributions
public double Scale
{
get { return _scale; }
set { SetParameters(_alpha, _beta, value, _location); }
}
@ -179,7 +182,6 @@ namespace MathNet.Numerics.Distributions
public double Location
{
get { return _location; }
set { SetParameters(_alpha, _beta, _scale, value); }
}
@ -200,7 +202,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -237,7 +238,7 @@ namespace MathNet.Numerics.Distributions
{
if (_alpha == 2)
{
return 2.0 * _scale * _scale;
return 2.0*_scale*_scale;
}
return Double.PositiveInfinity;
@ -253,7 +254,7 @@ namespace MathNet.Numerics.Distributions
{
if (_alpha == 2)
{
return Math.Sqrt(2.0) * _scale;
return Math.Sqrt(2.0)*_scale;
}
return Double.PositiveInfinity;
@ -324,7 +325,7 @@ namespace MathNet.Numerics.Distributions
static double LevyCumulativeDistribution(double scale, double location, double x)
{
// The parameters scale and location must be correct
return SpecialFunctions.Erfc(Math.Sqrt(scale / (2 * (x - location))));
return SpecialFunctions.Erfc(Math.Sqrt(scale/(2*(x - location))));
}
#endregion
@ -429,7 +430,7 @@ namespace MathNet.Numerics.Distributions
throw new NotSupportedException();
}
return (Math.Sqrt(scale / Constants.Pi2) * Math.Exp(-scale / (2 * (x - location)))) / Math.Pow(x - location, 1.5);
return (Math.Sqrt(scale/Constants.Pi2)*Math.Exp(-scale/(2*(x - location))))/Math.Pow(x - location, 1.5);
}
/// <summary>
@ -460,23 +461,23 @@ namespace MathNet.Numerics.Distributions
if (!1.0.AlmostEqual(alpha))
{
var theta = (1.0 / alpha) * Math.Atan(beta * Math.Tan(Constants.PiOver2 * alpha));
var angle = alpha * (randTheta + theta);
var part1 = beta * Math.Tan(Constants.PiOver2 * alpha);
var theta = (1.0/alpha)*Math.Atan(beta*Math.Tan(Constants.PiOver2*alpha));
var angle = alpha*(randTheta + theta);
var part1 = beta*Math.Tan(Constants.PiOver2*alpha);
var factor = Math.Pow(1.0 + (part1 * part1), 1.0 / (2.0 * alpha));
var factor1 = Math.Sin(angle) / Math.Pow(Math.Cos(randTheta), (1.0 / alpha));
var factor2 = Math.Pow(Math.Cos(randTheta - angle) / randW, (1 - alpha) / alpha);
var factor = Math.Pow(1.0 + (part1*part1), 1.0/(2.0*alpha));
var factor1 = Math.Sin(angle)/Math.Pow(Math.Cos(randTheta), (1.0/alpha));
var factor2 = Math.Pow(Math.Cos(randTheta - angle)/randW, (1 - alpha)/alpha);
return location + scale * (factor * factor1 * factor2);
return location + scale*(factor*factor1*factor2);
}
else
{
var part1 = Constants.PiOver2 + (beta * randTheta);
var summand = part1 * Math.Tan(randTheta);
var subtrahend = beta * Math.Log(Constants.PiOver2 * randW * Math.Cos(randTheta) / part1);
var part1 = Constants.PiOver2 + (beta*randTheta);
var summand = part1*Math.Tan(randTheta);
var subtrahend = beta*Math.Log(Constants.PiOver2*randW*Math.Cos(randTheta)/part1);
return location + scale * ((2.0 / Math.PI) * (summand - subtrahend));
return location + scale*((2.0/Math.PI)*(summand - subtrahend));
}
}
@ -543,4 +544,4 @@ namespace MathNet.Numerics.Distributions
}
}
}
}
}

61
src/Numerics/Distributions/Continuous/StudentT.cs

@ -92,8 +92,23 @@ namespace MathNet.Numerics.Distributions
/// <param name="dof">The degrees of freedom for the Student t-distribution.</param>
public StudentT(double location, double scale, double dof)
{
_random = new Random();
SetParameters(location, scale, dof);
}
/// <summary>
/// Initializes a new instance of the StudentT class with a particular location, scale and degrees of
/// freedom. The distribution will
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
/// </summary>
/// <param name="location">The location of the Student t-distribution.</param>
/// <param name="scale">The scale of the Student t-distribution.</param>
/// <param name="dof">The degrees of freedom for the Student t-distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public StudentT(double location, double scale, double dof, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(location, scale, dof);
RandomSource = new Random();
}
/// <summary>
@ -147,7 +162,6 @@ namespace MathNet.Numerics.Distributions
public double Location
{
get { return _location; }
set { SetParameters(value, _scale, _dof); }
}
@ -157,7 +171,6 @@ namespace MathNet.Numerics.Distributions
public double Scale
{
get { return _scale; }
set { SetParameters(_location, value, _dof); }
}
@ -167,7 +180,6 @@ namespace MathNet.Numerics.Distributions
public double DegreesOfFreedom
{
get { return _dof; }
set { SetParameters(_location, _scale, value); }
}
@ -179,7 +191,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -208,12 +219,12 @@ namespace MathNet.Numerics.Distributions
{
if (Double.IsPositiveInfinity(_dof))
{
return _scale * _scale;
return _scale*_scale;
}
if (_dof > 2.0)
{
return _dof * _scale * _scale / (_dof - 2.0);
return _dof*_scale*_scale/(_dof - 2.0);
}
return _dof > 1.0 ? Double.PositiveInfinity : Double.NaN;
@ -229,12 +240,12 @@ namespace MathNet.Numerics.Distributions
{
if (Double.IsPositiveInfinity(_dof))
{
return Math.Sqrt(_scale * _scale);
return Math.Sqrt(_scale*_scale);
}
if (_dof > 2.0)
{
return Math.Sqrt(_dof * _scale * _scale / (_dof - 2.0));
return Math.Sqrt(_dof*_scale*_scale/(_dof - 2.0));
}
return _dof > 1.0 ? Double.PositiveInfinity : Double.NaN;
@ -253,7 +264,7 @@ namespace MathNet.Numerics.Distributions
throw new NotSupportedException();
}
return (((_dof + 1.0) / 2.0) * (SpecialFunctions.DiGamma((1.0 + _dof) / 2.0) - SpecialFunctions.DiGamma(_dof / 2.0))) + Math.Log(Math.Sqrt(_dof) * SpecialFunctions.Beta(_dof / 2.0, 1.0 / 2.0));
return (((_dof + 1.0)/2.0)*(SpecialFunctions.DiGamma((1.0 + _dof)/2.0) - SpecialFunctions.DiGamma(_dof/2.0))) + Math.Log(Math.Sqrt(_dof)*SpecialFunctions.Beta(_dof/2.0, 1.0/2.0));
}
}
@ -322,11 +333,11 @@ namespace MathNet.Numerics.Distributions
return Normal.Density(_location, _scale, x);
}
var d = (x - _location) / _scale;
return Math.Exp(SpecialFunctions.GammaLn((_dof + 1.0) / 2.0) - SpecialFunctions.GammaLn(_dof / 2.0))
* Math.Pow(1.0 + (d * d / _dof), -0.5 * (_dof + 1.0))
/ Math.Sqrt(_dof * Math.PI)
/ _scale;
var d = (x - _location)/_scale;
return Math.Exp(SpecialFunctions.GammaLn((_dof + 1.0)/2.0) - SpecialFunctions.GammaLn(_dof/2.0))
*Math.Pow(1.0 + (d*d/_dof), -0.5*(_dof + 1.0))
/Math.Sqrt(_dof*Math.PI)
/_scale;
}
/// <summary>
@ -342,11 +353,11 @@ namespace MathNet.Numerics.Distributions
return Normal.DensityLn(_location, _scale, x);
}
var d = (x - _location) / _scale;
return SpecialFunctions.GammaLn((_dof + 1.0) / 2.0)
- (0.5 * ((_dof + 1.0) * Math.Log(1.0 + (d * d / _dof))))
- SpecialFunctions.GammaLn(_dof / 2.0)
- (0.5 * Math.Log(_dof * Math.PI)) - Math.Log(_scale);
var d = (x - _location)/_scale;
return SpecialFunctions.GammaLn((_dof + 1.0)/2.0)
- (0.5*((_dof + 1.0)*Math.Log(1.0 + (d*d/_dof))))
- SpecialFunctions.GammaLn(_dof/2.0)
- (0.5*Math.Log(_dof*Math.PI)) - Math.Log(_scale);
}
/// <summary>
@ -362,9 +373,9 @@ namespace MathNet.Numerics.Distributions
return Normal.CumulativeDistribution(_location, _scale, x);
}
var k = (x - _location) / _scale;
var h = _dof / (_dof + (k * k));
var ib = 0.5 * SpecialFunctions.BetaRegularized(_dof / 2.0, 0.5, h);
var k = (x - _location)/_scale;
var h = _dof/(_dof + (k*k));
var ib = 0.5*SpecialFunctions.BetaRegularized(_dof/2.0, 0.5, h);
return x <= _location ? ib : 1.0 - ib;
}
@ -383,8 +394,8 @@ namespace MathNet.Numerics.Distributions
internal static double SampleUnchecked(Random rnd, double location, double scale, double dof)
{
var n = Normal.SampleUncheckedBoxMuller(rnd).Item1;
var g = Gamma.SampleUnchecked(rnd, 0.5 * dof, 0.5);
return location + (scale * n * Math.Sqrt(dof / g));
var g = Gamma.SampleUnchecked(rnd, 0.5*dof, 0.5);
return location + (scale*n*Math.Sqrt(dof/g));
}
/// <summary>

43
src/Numerics/Distributions/Continuous/Weibull.cs

@ -78,8 +78,20 @@ namespace MathNet.Numerics.Distributions
/// <param name="scale">The inverse scale of the Weibull distribution.</param>
public Weibull(double shape, double scale)
{
_random = new Random();
SetParameters(shape, scale);
}
/// <summary>
/// Initializes a new instance of the Weibull class.
/// </summary>
/// <param name="shape">The shape of the Weibull distribution.</param>
/// <param name="scale">The inverse scale of the Weibull distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Weibull(double shape, double scale, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(shape, scale);
RandomSource = new Random();
}
/// <summary>
@ -131,7 +143,6 @@ namespace MathNet.Numerics.Distributions
public double Shape
{
get { return _shape; }
set { SetParameters(value, _scale); }
}
@ -141,7 +152,6 @@ namespace MathNet.Numerics.Distributions
public double Scale
{
get { return _scale; }
set { SetParameters(_shape, value); }
}
@ -153,7 +163,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -170,7 +179,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return _scale * SpecialFunctions.Gamma(1.0 + (1.0 / _shape)); }
get { return _scale*SpecialFunctions.Gamma(1.0 + (1.0/_shape)); }
}
/// <summary>
@ -178,7 +187,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return (_scale * _scale * SpecialFunctions.Gamma(1.0 + (2.0 / _shape))) - (Mean * Mean); }
get { return (_scale*_scale*SpecialFunctions.Gamma(1.0 + (2.0/_shape))) - (Mean*Mean); }
}
/// <summary>
@ -194,7 +203,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Entropy
{
get { return (Constants.EulerMascheroni * (1.0 - (1.0 / _shape))) + Math.Log(_scale / _shape) + 1.0; }
get { return (Constants.EulerMascheroni*(1.0 - (1.0/_shape))) + Math.Log(_scale/_shape) + 1.0; }
}
/// <summary>
@ -206,9 +215,9 @@ namespace MathNet.Numerics.Distributions
{
double mu = Mean;
double sigma = StdDev;
double sigma2 = sigma * sigma;
double sigma3 = sigma2 * sigma;
return ((_scale * _scale * _scale * SpecialFunctions.Gamma(1.0 + (3.0 / _shape))) - (3.0 * sigma2 * mu) - (mu * mu * mu)) / sigma3;
double sigma2 = sigma*sigma;
double sigma3 = sigma2*sigma;
return ((_scale*_scale*_scale*SpecialFunctions.Gamma(1.0 + (3.0/_shape))) - (3.0*sigma2*mu) - (mu*mu*mu))/sigma3;
}
}
@ -228,7 +237,7 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
return _scale * Math.Pow((_shape - 1.0) / _shape, 1.0 / _shape);
return _scale*Math.Pow((_shape - 1.0)/_shape, 1.0/_shape);
}
}
@ -237,7 +246,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Median
{
get { return _scale * Math.Pow(Constants.Ln2, 1.0 / _shape); }
get { return _scale*Math.Pow(Constants.Ln2, 1.0/_shape); }
}
/// <summary>
@ -267,10 +276,10 @@ namespace MathNet.Numerics.Distributions
{
if (x == 0.0 && _shape == 1.0)
{
return _shape / _scale;
return _shape/_scale;
}
return _shape * Math.Pow(x / _scale, _shape - 1.0) * Math.Exp(-Math.Pow(x, _shape) * _scalePowShapeInv) / _scale;
return _shape*Math.Pow(x/_scale, _shape - 1.0)*Math.Exp(-Math.Pow(x, _shape)*_scalePowShapeInv)/_scale;
}
return 0.0;
@ -290,7 +299,7 @@ namespace MathNet.Numerics.Distributions
return Math.Log(_shape) - Math.Log(_scale);
}
return Math.Log(_shape) + ((_shape - 1.0) * Math.Log(x / _scale)) - (Math.Pow(x, _shape) * _scalePowShapeInv) - Math.Log(_scale);
return Math.Log(_shape) + ((_shape - 1.0)*Math.Log(x/_scale)) - (Math.Pow(x, _shape)*_scalePowShapeInv) - Math.Log(_scale);
}
return double.NegativeInfinity;
@ -308,7 +317,7 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
return -SpecialFunctions.ExponentialMinusOne(-Math.Pow(x, _shape) * _scalePowShapeInv);
return -SpecialFunctions.ExponentialMinusOne(-Math.Pow(x, _shape)*_scalePowShapeInv);
}
#endregion
@ -324,7 +333,7 @@ namespace MathNet.Numerics.Distributions
internal static double SampleUnchecked(Random rnd, double shape, double scale)
{
var x = rnd.NextDouble();
return scale * Math.Pow(-Math.Log(x), 1.0 / shape);
return scale*Math.Pow(-Math.Log(x), 1.0/shape);
}
/// <summary>

24
src/Numerics/Distributions/Discrete/Bernoulli.cs

@ -59,8 +59,20 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="ArgumentOutOfRangeException">If the Bernoulli parameter is not in the range [0,1].</exception>
public Bernoulli(double p)
{
_random = new Random();
SetParameters(p);
}
/// <summary>
/// Initializes a new instance of the Bernoulli class.
/// </summary>
/// <param name="p">The probability of generating one.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentOutOfRangeException">If the Bernoulli parameter is not in the range [0,1].</exception>
public Bernoulli(double p, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(p);
RandomSource = new Random();
}
/// <summary>
@ -108,7 +120,6 @@ namespace MathNet.Numerics.Distributions
public double P
{
get { return _p; }
set { SetParameters(value); }
}
@ -120,7 +131,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -145,7 +155,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return Math.Sqrt(_p * (1.0 - _p)); }
get { return Math.Sqrt(_p*(1.0 - _p)); }
}
/// <summary>
@ -153,7 +163,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return _p * (1.0 - _p); }
get { return _p*(1.0 - _p); }
}
/// <summary>
@ -161,7 +171,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Entropy
{
get { return -(_p * Math.Log(_p)) - ((1.0 - _p) * Math.Log(1.0 - _p)); }
get { return -(_p*Math.Log(_p)) - ((1.0 - _p)*Math.Log(1.0 - _p)); }
}
/// <summary>
@ -169,7 +179,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Skewness
{
get { return (1.0 - (2.0 * _p)) / Math.Sqrt(_p * (1.0 - _p)); }
get { return (1.0 - (2.0*_p))/Math.Sqrt(_p*(1.0 - _p)); }
}
/// <summary>

41
src/Numerics/Distributions/Discrete/Binomial.cs

@ -66,8 +66,22 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="n"/> is negative.</exception>
public Binomial(double p, int n)
{
_random = new Random();
SetParameters(p, n);
}
/// <summary>
/// Initializes a new instance of the Binomial class.
/// </summary>
/// <param name="p">The success probability of a trial.</param>
/// <param name="n">The number of trials.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="p"/> is not in the interval [0.0,1.0].</exception>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="n"/> is negative.</exception>
public Binomial(double p, int n, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(p, n);
RandomSource = new Random();
}
/// <summary>
@ -124,7 +138,6 @@ namespace MathNet.Numerics.Distributions
public double P
{
get { return _p; }
set { SetParameters(value, _n); }
}
@ -134,7 +147,6 @@ namespace MathNet.Numerics.Distributions
public int N
{
get { return _n; }
set { SetParameters(_p, value); }
}
@ -146,7 +158,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -163,7 +174,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return _p * _n; }
get { return _p*_n; }
}
/// <summary>
@ -171,7 +182,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return Math.Sqrt(_p * (1.0 - _p) * _n); }
get { return Math.Sqrt(_p*(1.0 - _p)*_n); }
}
/// <summary>
@ -179,7 +190,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return _p * (1.0 - _p) * _n; }
get { return _p*(1.0 - _p)*_n; }
}
/// <summary>
@ -198,7 +209,7 @@ namespace MathNet.Numerics.Distributions
for (var i = 0; i <= _n; i++)
{
var p = Probability(i);
e -= p * Math.Log(p);
e -= p*Math.Log(p);
}
return e;
@ -210,7 +221,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Skewness
{
get { return (1.0 - (2.0 * _p)) / Math.Sqrt(_n * _p * (1.0 - _p)); }
get { return (1.0 - (2.0*_p))/Math.Sqrt(_n*_p*(1.0 - _p)); }
}
/// <summary>
@ -247,9 +258,9 @@ namespace MathNet.Numerics.Distributions
}
var cdf = 0.0;
for (var i = 0; i <= (int)Math.Floor(x); i++)
for (var i = 0; i <= (int) Math.Floor(x); i++)
{
cdf += Combinatorics.Combinations(_n, i) * Math.Pow(_p, i) * Math.Pow(1.0 - _p, _n - i);
cdf += Combinatorics.Combinations(_n, i)*Math.Pow(_p, i)*Math.Pow(1.0 - _p, _n - i);
}
return cdf;
@ -276,7 +287,7 @@ namespace MathNet.Numerics.Distributions
return 0;
}
return (int)Math.Floor((_n + 1) * _p);
return (int) Math.Floor((_n + 1)*_p);
}
}
@ -285,7 +296,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int Median
{
get { return (int)Math.Floor(_p * _n); }
get { return (int) Math.Floor(_p*_n); }
}
/// <summary>
@ -325,7 +336,7 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
return SpecialFunctions.Binomial(_n, k) * Math.Pow(_p, k) * Math.Pow(1.0 - _p, _n - k);
return SpecialFunctions.Binomial(_n, k)*Math.Pow(_p, k)*Math.Pow(1.0 - _p, _n - k);
}
/// <summary>
@ -365,7 +376,7 @@ namespace MathNet.Numerics.Distributions
return Double.NegativeInfinity;
}
return SpecialFunctions.BinomialLn(_n, k) + (k * Math.Log(_p)) + ((_n - k) * Math.Log(1.0 - _p));
return SpecialFunctions.BinomialLn(_n, k) + (k*Math.Log(_p)) + ((_n - k)*Math.Log(1.0 - _p));
}
#endregion

26
src/Numerics/Distributions/Discrete/Categorical.cs

@ -63,8 +63,21 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="ArgumentException">If any of the probabilities are negative or do not sum to one.</exception>
public Categorical(double[] probabilityMass)
{
_random = new Random();
SetParameters(probabilityMass);
}
/// <summary>
/// Initializes a new instance of the Categorical class.
/// </summary>
/// <param name="probabilityMass">An array of nonnegative ratios: this array does not need to be normalized
/// as this is often impossible using floating point arithmetic.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentException">If any of the probabilities are negative or do not sum to one.</exception>
public Categorical(double[] probabilityMass, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(probabilityMass);
RandomSource = new Random();
}
/// <summary>
@ -89,8 +102,8 @@ namespace MathNet.Numerics.Distributions
p[i] = histogram[i].Count;
}
_random = new Random();
SetParameters(p);
RandomSource = new Random();
}
/// <summary>
@ -184,7 +197,7 @@ namespace MathNet.Numerics.Distributions
/// exactly in a floating point representation.</remarks>
public double[] P
{
get { return (double[])_pmfNormalized.Clone(); }
get { return (double[]) _pmfNormalized.Clone(); }
set { SetParameters(value); }
}
@ -196,7 +209,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -237,7 +249,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Entropy
{
get { return _pmfNormalized.Sum(p => p * Math.Log(p)); }
get { return _pmfNormalized.Sum(p => p*Math.Log(p)); }
}
/// <summary>
@ -303,7 +315,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int Median
{
get { return (int)_pmfNormalized.Median(); }
get { return (int) _pmfNormalized.Median(); }
}
/// <summary>
@ -376,7 +388,7 @@ namespace MathNet.Numerics.Distributions
internal static int SampleUnchecked(Random rnd, double[] cdfUnnormalized)
{
// TODO : use binary search to speed up this procedure.
var u = rnd.NextDouble() * cdfUnnormalized[cdfUnnormalized.Length - 1];
var u = rnd.NextDouble()*cdfUnnormalized[cdfUnnormalized.Length - 1];
var idx = 0;
while (u > cdfUnnormalized[idx])

81
src/Numerics/Distributions/Discrete/ConwayMaxwellPoisson.cs

@ -87,16 +87,24 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="ConwayMaxwellPoisson"/> class.
/// </summary>
/// <param name="lambda">
/// The lambda parameter.
/// </param>
/// <param name="nu">
/// The nu parameter.
/// </param>
/// <param name="lambda">The lambda parameter.</param>
/// <param name="nu">The nu parameter.</param>
public ConwayMaxwellPoisson(double lambda, double nu)
{
_random = new Random();
SetParameters(lambda, nu);
}
/// <summary>
/// Initializes a new instance of the <see cref="ConwayMaxwellPoisson"/> class.
/// </summary>
/// <param name="lambda">The lambda parameter.</param>
/// <param name="nu">The nu parameter.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public ConwayMaxwellPoisson(double lambda, double nu, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(lambda, nu);
RandomSource = new Random();
}
/// <summary>
@ -144,7 +152,6 @@ namespace MathNet.Numerics.Distributions
public double Lambda
{
get { return _lambda; }
set { SetParameters(value, _nu); }
}
@ -155,7 +162,6 @@ namespace MathNet.Numerics.Distributions
public double Nu
{
get { return _nu; }
set { SetParameters(_lambda, value); }
}
@ -178,7 +184,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -212,28 +217,28 @@ namespace MathNet.Numerics.Distributions
var z = 1 + _lambda;
// The probability of the next term.
var a1 = _lambda * _lambda / Math.Pow(2, _nu);
var a1 = _lambda*_lambda/Math.Pow(2, _nu);
// The unnormalized mean.
var zx = _lambda;
// The contribution of the next term to the mean.
var ax1 = 2 * a1;
var ax1 = 2*a1;
for (var i = 3; i < 1000; i++)
{
var e = _lambda / Math.Pow(i, _nu);
var ex = _lambda / Math.Pow(i, _nu - 1) / (i - 1);
var a2 = a1 * e;
var ax2 = ax1 * ex;
var e = _lambda/Math.Pow(i, _nu);
var ex = _lambda/Math.Pow(i, _nu - 1)/(i - 1);
var a2 = a1*e;
var ax2 = ax1*ex;
var m = zx / z;
var upper = (zx + (ax1 / (1 - (ax2 / ax1)))) / z;
var lower = zx / (z + (a1 / (1 - (a2 / a1))));
var m = zx/z;
var upper = (zx + (ax1/(1 - (ax2/ax1))))/z;
var lower = zx/(z + (a1/(1 - (a2/a1))));
if ((ax2 < ax1) && (a2 < a1))
{
var r = (upper - lower) / m;
var r = (upper - lower)/m;
if (r < Tolerance)
{
break;
@ -246,7 +251,7 @@ namespace MathNet.Numerics.Distributions
ax1 = ax2;
}
_mean = zx / z;
_mean = zx/z;
return _mean;
}
}
@ -273,28 +278,28 @@ namespace MathNet.Numerics.Distributions
var z = 1 + _lambda;
// The probability of the next term.
var a1 = _lambda * _lambda / Math.Pow(2, _nu);
var a1 = _lambda*_lambda/Math.Pow(2, _nu);
// The unnormalized second moment.
var zxx = _lambda;
// The contribution of the next term to the second moment.
var axx1 = 4 * a1;
var axx1 = 4*a1;
for (var i = 3; i < 1000; i++)
{
var e = _lambda / Math.Pow(i, _nu);
var exx = _lambda / Math.Pow(i, _nu - 2) / (i - 1) / (i - 1);
var a2 = a1 * e;
var axx2 = axx1 * exx;
var e = _lambda/Math.Pow(i, _nu);
var exx = _lambda/Math.Pow(i, _nu - 2)/(i - 1)/(i - 1);
var a2 = a1*e;
var axx2 = axx1*exx;
var m = zxx / z;
var upper = (zxx + (axx1 / (1 - (axx2 / axx1)))) / z;
var lower = zxx / (z + (a1 / (1 - (a2 / a1))));
var m = zxx/z;
var upper = (zxx + (axx1/(1 - (axx2/axx1))))/z;
var lower = zxx/(z + (a1/(1 - (a2/a1))));
if ((axx2 < axx1) && (a2 < a1))
{
var r = (upper - lower) / m;
var r = (upper - lower)/m;
if (r < Tolerance)
{
break;
@ -308,7 +313,7 @@ namespace MathNet.Numerics.Distributions
}
var mean = Mean;
_variance = (zxx / z) - (mean * mean);
_variance = (zxx/z) - (mean*mean);
return _variance;
}
}
@ -398,7 +403,7 @@ namespace MathNet.Numerics.Distributions
/// </returns>
public double Probability(int k)
{
return Math.Pow(_lambda, k) / Math.Pow(SpecialFunctions.Factorial(k), _nu) / Z;
return Math.Pow(_lambda, k)/Math.Pow(SpecialFunctions.Factorial(k), _nu)/Z;
}
/// <summary>
@ -452,10 +457,10 @@ namespace MathNet.Numerics.Distributions
for (var i = 2; i < 1000; i++)
{
// The new addition for term i.
var e = lambda / Math.Pow(i, nu);
var e = lambda/Math.Pow(i, nu);
// The new term.
t = t * e;
t = t*e;
// The updated normalization constant.
z = z + t;
@ -463,7 +468,7 @@ namespace MathNet.Numerics.Distributions
// The stopping criterion.
if (e < 1)
{
if (t / (1 - e) / z < Tolerance)
if (t/(1 - e)/z < Tolerance)
{
break;
}
@ -486,14 +491,14 @@ namespace MathNet.Numerics.Distributions
internal static int SampleUnchecked(Random rnd, double lambda, double nu, double z)
{
var u = rnd.NextDouble();
var p = 1.0 / z;
var p = 1.0/z;
var cdf = p;
var i = 0;
while (u > cdf)
{
i++;
p = p * lambda / Math.Pow(i, nu);
p = p*lambda/Math.Pow(i, nu);
cdf += p;
}

33
src/Numerics/Distributions/Discrete/DiscreteUniform.cs

@ -64,8 +64,20 @@ namespace MathNet.Numerics.Distributions
/// <param name="upper">Upper bound; must be at least as large as <paramref name="lower"/>.</param>
public DiscreteUniform(int lower, int upper)
{
_random = new Random();
SetParameters(lower, upper);
}
/// <summary>
/// Initializes a new instance of the DiscreteUniform class.
/// </summary>
/// <param name="lower">Lower bound.</param>
/// <param name="upper">Upper bound; must be at least as large as <paramref name="lower"/>.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public DiscreteUniform(int lower, int upper, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(lower, upper);
RandomSource = new Random();
}
/// <summary>
@ -118,7 +130,6 @@ namespace MathNet.Numerics.Distributions
public int LowerBound
{
get { return _lower; }
set { SetParameters(value, _upper); }
}
@ -128,7 +139,6 @@ namespace MathNet.Numerics.Distributions
public int UpperBound
{
get { return _upper; }
set { SetParameters(_lower, value); }
}
@ -140,7 +150,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -157,7 +166,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return (_lower + _upper) / 2.0; }
get { return (_lower + _upper)/2.0; }
}
/// <summary>
@ -165,7 +174,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return Math.Sqrt((((_upper - _lower + 1.0) * (_upper - _lower + 1.0)) - 1.0) / 12.0); }
get { return Math.Sqrt((((_upper - _lower + 1.0)*(_upper - _lower + 1.0)) - 1.0)/12.0); }
}
/// <summary>
@ -173,7 +182,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return (((_upper - _lower + 1.0) * (_upper - _lower + 1.0)) - 1.0) / 12.0; }
get { return (((_upper - _lower + 1.0)*(_upper - _lower + 1.0)) - 1.0)/12.0; }
}
/// <summary>
@ -225,7 +234,7 @@ namespace MathNet.Numerics.Distributions
return 1.0;
}
return Math.Min(1.0, (Math.Floor(x) - _lower + 1) / (_upper - _lower + 1));
return Math.Min(1.0, (Math.Floor(x) - _lower + 1)/(_upper - _lower + 1));
}
#endregion
@ -237,7 +246,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int Mode
{
get { return (int)Math.Floor((_lower + _upper) / 2.0); }
get { return (int) Math.Floor((_lower + _upper)/2.0); }
}
/// <summary>
@ -245,7 +254,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int Median
{
get { return (int)Math.Floor((_lower + _upper) / 2.0); }
get { return (int) Math.Floor((_lower + _upper)/2.0); }
}
/// <summary>
@ -259,7 +268,7 @@ namespace MathNet.Numerics.Distributions
{
if (k >= _lower && k <= _upper)
{
return 1.0 / (_upper - _lower + 1);
return 1.0/(_upper - _lower + 1);
}
return 0.0;
@ -293,7 +302,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>A random sample from the discrete uniform distribution.</returns>
internal static int SampleUnchecked(Random rnd, int lower, int upper)
{
return (rnd.Next() % (upper - lower + 1)) + lower;
return (rnd.Next()%(upper - lower + 1)) + lower;
}
/// <summary>

33
src/Numerics/Distributions/Discrete/Geometric.cs

@ -59,8 +59,20 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="ArgumentOutOfRangeException">If the Geometric parameter is not in the range [0,1].</exception>
public Geometric(double p)
{
_random = new Random();
SetParameters(p);
}
/// <summary>
/// Initializes a new instance of the Geometric class.
/// </summary>
/// <param name="p">The probability of generating one.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentOutOfRangeException">If the Geometric parameter is not in the range [0,1].</exception>
public Geometric(double p, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(p);
RandomSource = new Random();
}
/// <summary>
@ -122,7 +134,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -139,7 +150,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return 1.0 / _p; }
get { return 1.0/_p; }
}
/// <summary>
@ -147,7 +158,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return (1.0 - _p) / (_p * _p); }
get { return (1.0 - _p)/(_p*_p); }
}
/// <summary>
@ -155,7 +166,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return Math.Sqrt(1.0 - _p) / _p; }
get { return Math.Sqrt(1.0 - _p)/_p; }
}
/// <summary>
@ -163,7 +174,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Entropy
{
get { return ((-_p * Math.Log(_p, 2.0)) - ((1.0 - _p) * Math.Log(1.0 - _p, 2.0))) / _p; }
get { return ((-_p*Math.Log(_p, 2.0)) - ((1.0 - _p)*Math.Log(1.0 - _p, 2.0)))/_p; }
}
/// <summary>
@ -172,7 +183,7 @@ namespace MathNet.Numerics.Distributions
/// <remarks>Throws a not supported exception.</remarks>
public double Skewness
{
get { return (2.0 - _p) / Math.Sqrt(1.0 - _p); }
get { return (2.0 - _p)/Math.Sqrt(1.0 - _p); }
}
/// <summary>
@ -202,7 +213,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int Median
{
get { return (int)Math.Ceiling(-Constants.Ln2 / Math.Log(1 - _p)); }
get { return (int) Math.Ceiling(-Constants.Ln2/Math.Log(1 - _p)); }
}
/// <summary>
@ -235,7 +246,7 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
return Math.Pow(1.0 - _p, k - 1) * _p;
return Math.Pow(1.0 - _p, k - 1)*_p;
}
/// <summary>
@ -252,7 +263,7 @@ namespace MathNet.Numerics.Distributions
return Double.NegativeInfinity;
}
return ((k - 1) * Math.Log(1.0 - _p)) + Math.Log(_p);
return ((k - 1)*Math.Log(1.0 - _p)) + Math.Log(_p);
}
#endregion
@ -267,7 +278,7 @@ namespace MathNet.Numerics.Distributions
/// </returns>
internal static int SampleUnchecked(Random rnd, double p)
{
return p == 1.0 ? 1 : (int)Math.Ceiling(-Math.Log(1.0 - rnd.NextDouble(), 1.0 - p));
return p == 1.0 ? 1 : (int) Math.Ceiling(-Math.Log(1.0 - rnd.NextDouble(), 1.0 - p));
}
/// <summary>

249
src/Numerics/Distributions/Discrete/Hypergeometric.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 MathNet.Numerics.Properties;
using System.Collections.Generic;
namespace MathNet.Numerics.Distributions
{
using System;
using System.Collections.Generic;
using Properties;
/// <summary>
/// This class implements functionality for the Hypergeometric distribution. This distribution is
@ -50,19 +51,19 @@ namespace MathNet.Numerics.Distributions
public class Hypergeometric : IDiscreteDistribution
{
/// <summary>
/// The size of the population.
/// The size of the population (N).
/// </summary>
int _populationSize;
int _population;
/// <summary>
/// The m parameter of the distribution.
/// The number successes within the population (K, M).
/// </summary>
int _m;
int _success;
/// <summary>
/// The n parameter (number to draw) of the distribution.
/// The number of draws without replacement (n).
/// </summary>
int _n;
int _draws;
/// <summary>
/// The distribution's random number generator.
@ -72,48 +73,61 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the Hypergeometric class.
/// </summary>
/// <param name="populationSize">The population size.</param>
/// <param name="m">The m parameter of the distribution.</param>
/// <param name="n">The n parameter of the distribution.</param>
public Hypergeometric(int populationSize, int m, int n)
/// <param name="population">The size of the population (N).</param>
/// <param name="success">The number successes within the population (K, M).</param>
/// <param name="draws">The number of draws without replacement (n).</param>
public Hypergeometric(int population, int success, int draws)
{
_random = new Random();
SetParameters(population, success, draws);
}
/// <summary>
/// Initializes a new instance of the Hypergeometric class.
/// </summary>
/// <param name="population">The size of the population (N).</param>
/// <param name="success">The number successes within the population (K, M).</param>
/// <param name="draws">The number of draws without replacement (n).</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Hypergeometric(int population, int success, int draws, Random randomSource)
{
SetParameters(populationSize, m, n);
RandomSource = new Random();
_random = randomSource ?? new Random();
SetParameters(population, success, draws);
}
/// <summary>
/// Sets the parameters of the distribution after checking their validity.
/// </summary>
/// <param name="total">The Total parameter of the distribution.</param>
/// <param name="m">The m parameter of the distribution.</param>
/// <param name="n">The n parameter of the distribution.</param>
void SetParameters(int total, int m, int n)
/// <param name="population">The size of the population (N).</param>
/// <param name="success">The number successes within the population (K, M).</param>
/// <param name="draws">The number of draws without replacement (n).</param>
void SetParameters(int population, int success, int draws)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(total, m, n))
if (Control.CheckDistributionParameters && !IsValidParameterSet(population, success, draws))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
_populationSize = total;
_m = m;
_n = n;
_population = population;
_success = success;
_draws = draws;
}
/// <summary>
/// Checks whether the parameters of the distribution are valid.
/// </summary>
/// <param name="total">The Total parameter of the distribution.</param>
/// <param name="m">The m parameter of the distribution.</param>
/// <param name="n">The n parameter of the distribution.</param>
/// <param name="population">The size of the population (N).</param>
/// <param name="success">The number successes within the population (K, M).</param>
/// <param name="draws">The number of draws without replacement (n).</param>
/// <returns><c>true</c> when the parameters are valid, <c>false</c> otherwise.</returns>
static bool IsValidParameterSet(int total, int m, int n)
static bool IsValidParameterSet(int population, int success, int draws)
{
if (total < 0 || m < 0 || n < 0)
if (population < 0 || success < 0 || draws < 0)
{
return false;
}
if (m > total || n > total)
if (success > population || draws > population)
{
return false;
}
@ -122,30 +136,60 @@ namespace MathNet.Numerics.Distributions
}
/// <summary>
/// Gets or sets the population size.
/// Gets or sets the size of the population (N).
/// </summary>
public int Population
{
get { return _population; }
set { SetParameters(value, _success, _draws); }
}
/// <summary>
/// Gets or sets the number of draws without replacement (n).
/// </summary>
public int Draws
{
get { return _draws; }
set { SetParameters(_population, value, _draws); }
}
/// <summary>
/// Gets or sets the number successes within the population (K, M).
/// </summary>
public int Success
{
get { return _success; }
set { SetParameters(_population, _success, value); }
}
/// <summary>
/// Gets or sets the size of the population (N).
/// </summary>
[Obsolete("Use Population instead. Scheduled for removal in v3.0.")]
public int PopulationSize
{
get { return _populationSize; }
set { SetParameters(value, _m, _n); }
get { return _population; }
set { SetParameters(value, _success, _draws); }
}
/// <summary>
/// Gets or sets the n parameter of the distribution.
/// Gets or sets the number of draws without replacement (n).
/// </summary>
[Obsolete("Use Draws instead. Scheduled for removal in v3.0.")]
public int N
{
get { return _n; }
set { SetParameters(_populationSize, value, _n); }
get { return _draws; }
set { SetParameters(_population, value, _draws); }
}
/// <summary>
/// Gets or sets the m parameter of the distribution.
/// Gets or sets the number successes within the population (K, M).
/// </summary>
[Obsolete("Use Success instead. Scheduled for removal in v3.0.")]
public int M
{
get { return _m; }
set { SetParameters(_populationSize, _m, value); }
get { return _success; }
set { SetParameters(_population, _success, value); }
}
/// <summary>
@ -156,18 +200,15 @@ namespace MathNet.Numerics.Distributions
/// </returns>
public override string ToString()
{
return "Hypergeometric(N = " + _populationSize + ", m = " + _m + ", n = " + _n + ")";
return "Hypergeometric(N = " + _population + ", M = " + _success + ", n = " + _draws + ")";
}
#region IDistribution Members
/// <summary>
/// Gets or sets the random number generator which is used to draw random samples.
/// </summary>
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -184,7 +225,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return (double)_m * _n / _populationSize; }
get { return (double) _success*_draws/_population; }
}
/// <summary>
@ -192,7 +233,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return _n * _m * (_populationSize - _n) * (_populationSize - _m) / (_populationSize * _populationSize * (_populationSize - 1.0)); }
get { return _draws*_success*(_population - _draws)*(_population - _success)/(_population*_population*(_population - 1.0)); }
}
/// <summary>
@ -216,48 +257,15 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Skewness
{
get { return (Math.Sqrt(_populationSize - 1.0) * (_populationSize - (2 * _n)) * (_populationSize - (2 * _m))) / (Math.Sqrt(_n * _m * (_populationSize - _m) * (_populationSize - _n)) * (_populationSize - 2.0)); }
}
/// <summary>
/// Computes the cumulative distribution function of the distribution.
/// </summary>
/// <param name="x">The location at which to compute the cumulative density.</param>
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
int alpha = Minimum;
int beta = Maximum;
if (x <= alpha)
{
return 0.0;
}
if (x > beta)
{
return 1.0;
}
var sum = 0.0;
var k = (int)Math.Ceiling(x - alpha) - 1;
for (var i = alpha; i <= alpha + k; i++)
{
sum += SpecialFunctions.Binomial(_m, i) * SpecialFunctions.Binomial(_populationSize - _m, _n - i);
}
return sum / SpecialFunctions.Binomial(_populationSize, _n);
get { return (Math.Sqrt(_population - 1.0)*(_population - (2*_draws))*(_population - (2*_success)))/(Math.Sqrt(_draws*_success*(_population - _success)*(_population - _draws))*(_population - 2.0)); }
}
#endregion
#region IDiscreteDistribution Members
/// <summary>
/// Gets the mode of the distribution.
/// </summary>
public int Mode
{
get { return (_n + 1) * (_m + 1) / (_populationSize + 2); }
get { return (_draws + 1)*(_success + 1)/(_population + 2); }
}
/// <summary>
@ -273,7 +281,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int Minimum
{
get { return Math.Max(0, _n + _m - _populationSize); }
get { return Math.Max(0, _draws + _success - _population); }
}
/// <summary>
@ -281,11 +289,11 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int Maximum
{
get { return Math.Min(_m, _n); }
get { return Math.Min(_success, _draws); }
}
/// <summary>
/// Computes values of the probability mass function.
/// Computes values of the probability mass function (PMF), i.e. P(X = x).
/// </summary>
/// <param name="k">The location in the domain where we want to evaluate the probability mass function.</param>
/// <returns>
@ -293,11 +301,11 @@ namespace MathNet.Numerics.Distributions
/// </returns>
public double Probability(int k)
{
return SpecialFunctions.Binomial(_m, k) * SpecialFunctions.Binomial(_populationSize - _m, _n - k) / SpecialFunctions.Binomial(_populationSize, _n);
return SpecialFunctions.Binomial(_success, k)*SpecialFunctions.Binomial(_population - _success, _draws - k)/SpecialFunctions.Binomial(_population, _draws);
}
/// <summary>
/// Computes values of the log probability mass function.
/// Computes values of the log probability mass function (lnPMF), i.e. ln(P(X = x)).
/// </summary>
/// <param name="k">The location in the domain where we want to evaluate the log probability mass function.</param>
/// <returns>
@ -308,34 +316,57 @@ namespace MathNet.Numerics.Distributions
return Math.Log(Probability(k));
}
#endregion
/// <summary>
/// Computes the cumulative distribution function (CDF) of the distribution, i.e. P(X &lt;= x).
/// </summary>
/// <param name="x">The location at which to compute the cumulative density.</param>
/// <returns>the cumulative density at <paramref name="x"/>.</returns>
public double CumulativeDistribution(double x)
{
if (x < Minimum)
{
return 0.0;
}
if (x >= Maximum)
{
return 1.0;
}
var k = (int) Math.Floor(x);
var denominatorLn = SpecialFunctions.BinomialLn(_population, _draws);
var sum = 0.0;
for (var i = 0; i <= k; i++)
{
sum += Math.Exp(SpecialFunctions.BinomialLn(_success, i) + SpecialFunctions.BinomialLn(_population - _success, _draws - i) - denominatorLn);
}
return sum;
}
/// <summary>
/// Generates a sample from the Hypergeometric distribution without doing parameter checking.
/// </summary>
/// <param name="rnd">The random number generator to use.</param>
/// <param name="size">The Total parameter of the distribution.</param>
/// <param name="m">The m parameter of the distribution.</param>
/// <param name="n">The n parameter of the distribution.</param>
/// <param name="population">The size of the population (N).</param>
/// <param name="success">The number successes within the population (K, M).</param>
/// <param name="draws">The n parameter of the distribution.</param>
/// <returns>a random number from the Hypergeometric distribution.</returns>
internal static int SampleUnchecked(Random rnd, int size, int m, int n)
internal static int SampleUnchecked(Random rnd, int population, int success, int draws)
{
var x = 0;
do
{
var p = (double)m / size;
var p = (double) success/population;
var r = rnd.NextDouble();
if (r < p)
{
x++;
m--;
success--;
}
size--;
n--;
}
while (0 < n);
population--;
draws--;
} while (0 < draws);
return x;
}
@ -346,7 +377,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>The number of successes in n trials.</returns>
public int Sample()
{
return SampleUnchecked(RandomSource, _populationSize, _m, _n);
return SampleUnchecked(RandomSource, _population, _success, _draws);
}
/// <summary>
@ -357,7 +388,7 @@ namespace MathNet.Numerics.Distributions
{
while (true)
{
yield return SampleUnchecked(RandomSource, _populationSize, _m, _n);
yield return SampleUnchecked(RandomSource, _population, _success, _draws);
}
}
@ -365,36 +396,36 @@ namespace MathNet.Numerics.Distributions
/// Samples a random variable.
/// </summary>
/// <param name="rnd">The random number generator to use.</param>
/// <param name="populationSize">The population size.</param>
/// <param name="m">The m parameter of the distribution.</param>
/// <param name="n">The n parameter of the distribution.</param>
public static int Sample(Random rnd, int populationSize, int m, int n)
/// <param name="population">The size of the population (N).</param>
/// <param name="success">The number successes within the population (K, M).</param>
/// <param name="draws">The number of draws without replacement (n).</param>
public static int Sample(Random rnd, int population, int success, int draws)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(populationSize, m, n))
if (Control.CheckDistributionParameters && !IsValidParameterSet(population, success, draws))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
return SampleUnchecked(rnd, populationSize, m, n);
return SampleUnchecked(rnd, population, success, draws);
}
/// <summary>
/// Samples a sequence of this random variable.
/// </summary>
/// <param name="rnd">The random number generator to use.</param>
/// <param name="populationSize">The population size.</param>
/// <param name="m">The m parameter of the distribution.</param>
/// <param name="n">The n parameter of the distribution.</param>
public static IEnumerable<int> Samples(Random rnd, int populationSize, int m, int n)
/// <param name="population">The size of the population (N).</param>
/// <param name="success">The number successes within the population (K, M).</param>
/// <param name="draws">The number of draws without replacement (n).</param>
public static IEnumerable<int> Samples(Random rnd, int population, int success, int draws)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(populationSize, m, n))
if (Control.CheckDistributionParameters && !IsValidParameterSet(population, success, draws))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
while (true)
{
yield return SampleUnchecked(rnd, populationSize, m, n);
yield return SampleUnchecked(rnd, population, success, draws);
}
}
}

40
src/Numerics/Distributions/Discrete/NegativeBinomial.cs

@ -64,7 +64,6 @@ namespace MathNet.Numerics.Distributions
public double R
{
get { return _r; }
set { SetParameters(value, _p); }
}
@ -74,7 +73,6 @@ namespace MathNet.Numerics.Distributions
public double P
{
get { return _p; }
set { SetParameters(_r, value); }
}
@ -85,8 +83,20 @@ namespace MathNet.Numerics.Distributions
/// <param name="p">The probability of a trial resulting in success.</param>
public NegativeBinomial(double r, double p)
{
_random = new Random();
SetParameters(r, p);
}
/// <summary>
/// Initializes a new instance of the <see cref="NegativeBinomial"/> class.
/// </summary>
/// <param name="r">The number of trials.</param>
/// <param name="p">The probability of a trial resulting in success.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public NegativeBinomial(double r, double p, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(r, p);
RandomSource = new Random();
}
/// <summary>
@ -146,7 +156,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -163,7 +172,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return _r * (1.0 - _p) / _p; }
get { return _r*(1.0 - _p)/_p; }
}
/// <summary>
@ -171,7 +180,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Variance
{
get { return _r * (1.0 - _p) / (_p * _p); }
get { return _r*(1.0 - _p)/(_p*_p); }
}
/// <summary>
@ -179,7 +188,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double StdDev
{
get { return Math.Sqrt(_r * (1.0 - _p)) / _p; }
get { return Math.Sqrt(_r*(1.0 - _p))/_p; }
}
/// <summary>
@ -195,7 +204,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Skewness
{
get { return (2.0 - _p) / Math.Sqrt(_r * (1.0 - _p)); }
get { return (2.0 - _p)/Math.Sqrt(_r*(1.0 - _p)); }
}
/// <summary>
@ -217,7 +226,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int Mode
{
get { return _r > 1.0 ? (int)Math.Floor((_r - 1.0) * (1.0 - _p) / _p) : 0; }
get { return _r > 1.0 ? (int) Math.Floor((_r - 1.0)*(1.0 - _p)/_p) : 0; }
}
/// <summary>
@ -256,8 +265,8 @@ namespace MathNet.Numerics.Distributions
var ln = SpecialFunctions.GammaLn(_r + k)
- SpecialFunctions.GammaLn(_r)
- SpecialFunctions.GammaLn(k + 1.0)
+ (_r * Math.Log(_p))
+ (k * Math.Log(1.0 - _p));
+ (_r*Math.Log(_p))
+ (k*Math.Log(1.0 - _p));
return Math.Exp(ln);
}
@ -273,8 +282,8 @@ namespace MathNet.Numerics.Distributions
var ln = SpecialFunctions.GammaLn(_r + k)
- SpecialFunctions.GammaLn(_r)
- SpecialFunctions.GammaLn(k + 1.0)
+ (_r * Math.Log(_p))
+ (k * Math.Log(1.0 - _p));
+ (_r*Math.Log(_p))
+ (k*Math.Log(1.0 - _p));
return ln;
}
@ -296,9 +305,8 @@ namespace MathNet.Numerics.Distributions
do
{
k = k + 1;
p1 = p1 * rnd.NextDouble();
}
while (p1 >= c);
p1 = p1*rnd.NextDouble();
} while (p1 >= c);
return k - 1;
}

44
src/Numerics/Distributions/Discrete/Poisson.cs

@ -56,7 +56,6 @@ namespace MathNet.Numerics.Distributions
public double Lambda
{
get { return _lambda; }
set { SetParameters(value); }
}
@ -67,8 +66,20 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="System.ArgumentOutOfRangeException">If <paramref name="lambda"/> is equal or less then 0.0.</exception>
public Poisson(double lambda)
{
_random = new Random();
SetParameters(lambda);
}
/// <summary>
/// Initializes a new instance of the <see cref="Poisson"/> class.
/// </summary>
/// <param name="lambda">The Poisson distribution parameter λ.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="System.ArgumentOutOfRangeException">If <paramref name="lambda"/> is equal or less then 0.0.</exception>
public Poisson(double lambda, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(lambda);
RandomSource = new Random();
}
/// <summary>
@ -115,7 +126,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -157,7 +167,7 @@ namespace MathNet.Numerics.Distributions
/// <remarks>Approximation, see Wikipedia <a href="http://en.wikipedia.org/wiki/Poisson_distribution">Poisson distribution</a></remarks>
public double Entropy
{
get { return (0.5 * Math.Log(2 * Constants.Pi * Constants.E * _lambda)) - (1.0 / (12.0 * _lambda)) - (1.0 / (24.0 * _lambda * _lambda)) - (19.0 / (360.0 * _lambda * _lambda * _lambda)); }
get { return (0.5*Math.Log(2*Constants.Pi*Constants.E*_lambda)) - (1.0/(12.0*_lambda)) - (1.0/(24.0*_lambda*_lambda)) - (19.0/(360.0*_lambda*_lambda*_lambda)); }
}
/// <summary>
@ -165,7 +175,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Skewness
{
get { return 1.0 / Math.Sqrt(_lambda); }
get { return 1.0/Math.Sqrt(_lambda); }
}
/// <summary>
@ -203,7 +213,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int Mode
{
get { return (int)Math.Floor(_lambda); }
get { return (int) Math.Floor(_lambda); }
}
/// <summary>
@ -212,7 +222,7 @@ namespace MathNet.Numerics.Distributions
/// <remarks>Approximation, see Wikipedia <a href="http://en.wikipedia.org/wiki/Poisson_distribution">Poisson distribution</a></remarks>
public int Median
{
get { return (int)Math.Floor(_lambda + (1.0 / 3.0) - (0.02 / _lambda)); }
get { return (int) Math.Floor(_lambda + (1.0/3.0) - (0.02/_lambda)); }
}
/// <summary>
@ -222,7 +232,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the probability mass at location <paramref name="k"/>.</returns>
public double Probability(int k)
{
return Math.Exp(-_lambda + (k * Math.Log(_lambda)) - SpecialFunctions.FactorialLn(k));
return Math.Exp(-_lambda + (k*Math.Log(_lambda)) - SpecialFunctions.FactorialLn(k));
}
/// <summary>
@ -232,7 +242,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>the log probability mass at location <paramref name="k"/>.</returns>
public double ProbabilityLn(int k)
{
return -_lambda + (k * Math.Log(_lambda)) - SpecialFunctions.FactorialLn(k);
return -_lambda + (k*Math.Log(_lambda)) - SpecialFunctions.FactorialLn(k);
}
#endregion
@ -277,26 +287,26 @@ namespace MathNet.Numerics.Distributions
/// The article is on pages 29-35. The algorithm given here is on page 32. </remarks>
static int DoSampleLarge(Random rnd, double lambda)
{
var c = 0.767 - (3.36 / lambda);
var beta = Math.PI / Math.Sqrt(3.0 * lambda);
var alpha = beta * lambda;
var c = 0.767 - (3.36/lambda);
var beta = Math.PI/Math.Sqrt(3.0*lambda);
var alpha = beta*lambda;
var k = Math.Log(c) - lambda - Math.Log(beta);
for (;;)
{
var u = rnd.NextDouble();
var x = (alpha - Math.Log((1.0 - u) / u)) / beta;
var n = (int)Math.Floor(x + 0.5);
var x = (alpha - Math.Log((1.0 - u)/u))/beta;
var n = (int) Math.Floor(x + 0.5);
if (n < 0)
{
continue;
}
var v = rnd.NextDouble();
var y = alpha - (beta * x);
var y = alpha - (beta*x);
var temp = 1.0 + Math.Exp(y);
var lhs = y + Math.Log(v / (temp * temp));
var rhs = k + (n * Math.Log(lambda)) - SpecialFunctions.FactorialLn(n);
var lhs = y + Math.Log(v/(temp*temp));
var rhs = k + (n*Math.Log(lambda)) - SpecialFunctions.FactorialLn(n);
if (lhs <= rhs)
{
return n;

43
src/Numerics/Distributions/Discrete/Zipf.cs

@ -62,16 +62,24 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Initializes a new instance of the <see cref="Zipf"/> class.
/// </summary>
/// <param name="s">
/// The s parameter of the distribution.
/// </param>
/// <param name="n">
/// The n parameter of the distribution.
/// </param>
/// <param name="s">The s parameter of the distribution.</param>
/// <param name="n">The n parameter of the distribution.</param>
public Zipf(double s, int n)
{
_random = new Random();
SetParameters(s, n);
}
/// <summary>
/// Initializes a new instance of the <see cref="Zipf"/> class.
/// </summary>
/// <param name="s">The s parameter of the distribution.</param>
/// <param name="n">The n parameter of the distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Zipf(double s, int n, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(s, n);
RandomSource = new Random();
}
/// <summary>
@ -112,7 +120,6 @@ namespace MathNet.Numerics.Distributions
public double S
{
get { return _s; }
set { SetParameters(value, _n); }
}
@ -122,7 +129,6 @@ namespace MathNet.Numerics.Distributions
public int N
{
get { return _n; }
set { SetParameters(_s, value); }
}
@ -143,7 +149,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource
{
get { return _random; }
set
{
if (value == null)
@ -160,7 +165,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get { return SpecialFunctions.GeneralHarmonic(_n, _s - 1.0) / SpecialFunctions.GeneralHarmonic(_n, _s); }
get { return SpecialFunctions.GeneralHarmonic(_n, _s - 1.0)/SpecialFunctions.GeneralHarmonic(_n, _s); }
}
/// <summary>
@ -176,7 +181,7 @@ namespace MathNet.Numerics.Distributions
}
var generalHarmonicsNS = SpecialFunctions.GeneralHarmonic(_n, _s);
return (SpecialFunctions.GeneralHarmonic(_n, _s - 2) * SpecialFunctions.GeneralHarmonic(_n, _s)) - (Math.Pow(SpecialFunctions.GeneralHarmonic(_n, _s - 1), 2) / (generalHarmonicsNS * generalHarmonicsNS));
return (SpecialFunctions.GeneralHarmonic(_n, _s - 2)*SpecialFunctions.GeneralHarmonic(_n, _s)) - (Math.Pow(SpecialFunctions.GeneralHarmonic(_n, _s - 1), 2)/(generalHarmonicsNS*generalHarmonicsNS));
}
}
@ -198,10 +203,10 @@ namespace MathNet.Numerics.Distributions
double sum = 0;
for (var i = 0; i < _n; i++)
{
sum += Math.Log(i + 1) / Math.Pow(i + 1, _s);
sum += Math.Log(i + 1)/Math.Pow(i + 1, _s);
}
return ((_s / SpecialFunctions.GeneralHarmonic(_n, _s)) * sum) + Math.Log(SpecialFunctions.GeneralHarmonic(_n, _s));
return ((_s/SpecialFunctions.GeneralHarmonic(_n, _s))*sum) + Math.Log(SpecialFunctions.GeneralHarmonic(_n, _s));
}
}
@ -217,7 +222,7 @@ namespace MathNet.Numerics.Distributions
throw new NotSupportedException();
}
return ((SpecialFunctions.GeneralHarmonic(_n, _s - 3) * Math.Pow(SpecialFunctions.GeneralHarmonic(_n, _s), 2)) - (SpecialFunctions.GeneralHarmonic(_n, _s - 1) * ((3 * SpecialFunctions.GeneralHarmonic(_n, _s - 2) * SpecialFunctions.GeneralHarmonic(_n, _s)) - Math.Pow(SpecialFunctions.GeneralHarmonic(_n, _s - 1), 2)))) / Math.Pow((SpecialFunctions.GeneralHarmonic(_n, _s - 2) * SpecialFunctions.GeneralHarmonic(_n, _s)) - Math.Pow(SpecialFunctions.GeneralHarmonic(_n, _s - 1), 2), 1.5);
return ((SpecialFunctions.GeneralHarmonic(_n, _s - 3)*Math.Pow(SpecialFunctions.GeneralHarmonic(_n, _s), 2)) - (SpecialFunctions.GeneralHarmonic(_n, _s - 1)*((3*SpecialFunctions.GeneralHarmonic(_n, _s - 2)*SpecialFunctions.GeneralHarmonic(_n, _s)) - Math.Pow(SpecialFunctions.GeneralHarmonic(_n, _s - 1), 2))))/Math.Pow((SpecialFunctions.GeneralHarmonic(_n, _s - 2)*SpecialFunctions.GeneralHarmonic(_n, _s)) - Math.Pow(SpecialFunctions.GeneralHarmonic(_n, _s - 1), 2), 1.5);
}
}
@ -233,7 +238,7 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
return SpecialFunctions.GeneralHarmonic((int)x, _s) / SpecialFunctions.GeneralHarmonic(_n, _s);
return SpecialFunctions.GeneralHarmonic((int) x, _s)/SpecialFunctions.GeneralHarmonic(_n, _s);
}
#endregion
@ -281,7 +286,7 @@ namespace MathNet.Numerics.Distributions
/// </returns>
public double Probability(int k)
{
return (1.0 / Math.Pow(k, _s)) / SpecialFunctions.GeneralHarmonic(_n, _s);
return (1.0/Math.Pow(k, _s))/SpecialFunctions.GeneralHarmonic(_n, _s);
}
/// <summary>
@ -313,12 +318,12 @@ namespace MathNet.Numerics.Distributions
r = rnd.NextDouble();
}
var p = 1.0 / SpecialFunctions.GeneralHarmonic(n, s);
var p = 1.0/SpecialFunctions.GeneralHarmonic(n, s);
int i;
var sum = 0.0;
for (i = 1; i <= n; i++)
{
sum += p / Math.Pow(i, s);
sum += p/Math.Pow(i, s);
if (sum >= r)
{
break;

100
src/Numerics/Distributions/Multivariate/Dirichlet.cs

@ -48,12 +48,12 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// The Dirichlet distribution parameters.
/// </summary>
private double[] _alpha;
double[] _alpha;
/// <summary>
/// The distribution's random number generator.
/// </summary>
private Random _random;
Random _random;
/// <summary>
/// Initializes a new instance of the Dirichlet class. The distribution will
@ -62,21 +62,27 @@ namespace MathNet.Numerics.Distributions
/// <param name="alpha">An array with the Dirichlet parameters.</param>
public Dirichlet(double[] alpha)
{
_random = new Random();
SetParameters(alpha);
RandomSource = new Random();
}
/// <summary>
/// Initializes a new instance of the <see cref="Dirichlet"/> class.
/// <seealso cref="System.Random"/>
/// random number generator.
/// Initializes a new instance of the Dirichlet class. The distribution will
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
/// </summary>
/// <param name="alpha">
/// The value of each parameter of the Dirichlet distribution.
/// </param>
/// <param name="k">
/// The dimension of the Dirichlet distribution.
/// </param>
/// <param name="alpha">An array with the Dirichlet parameters.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Dirichlet(double[] alpha, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(alpha);
}
/// <summary>
/// Initializes a new instance of the <see cref="Dirichlet"/> class.
/// <seealso cref="System.Random"/>random number generator.</summary>
/// <param name="alpha">The value of each parameter of the Dirichlet distribution.</param>
/// <param name="k">The dimension of the Dirichlet distribution.</param>
public Dirichlet(double alpha, int k)
{
// Create a parameter structure.
@ -86,8 +92,27 @@ namespace MathNet.Numerics.Distributions
parm[i] = alpha;
}
_random = new Random();
SetParameters(parm);
}
/// <summary>
/// Initializes a new instance of the <see cref="Dirichlet"/> class.
/// <seealso cref="System.Random"/>random number generator.</summary>
/// <param name="alpha">The value of each parameter of the Dirichlet distribution.</param>
/// <param name="k">The dimension of the Dirichlet distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Dirichlet(double alpha, int k, Random randomSource)
{
// Create a parameter structure.
var parm = new double[k];
for (var i = 0; i < k; i++)
{
parm[i] = alpha;
}
_random = randomSource ?? new Random();
SetParameters(parm);
RandomSource = new Random();
}
/// <summary>
@ -109,7 +134,7 @@ namespace MathNet.Numerics.Distributions
{
return false;
}
if (t > 0.0)
{
allzero = false;
@ -124,14 +149,14 @@ namespace MathNet.Numerics.Distributions
/// </summary>
/// <param name="alpha">The parameters of the Dirichlet distribution.</param>
/// <exception cref="ArgumentOutOfRangeException">When the parameters don't pass the <see cref="IsValidParameterSet"/> function.</exception>
private void SetParameters(double[] alpha)
void SetParameters(double[] alpha)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(alpha))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
_alpha = (double[])alpha.Clone();
_alpha = (double[]) alpha.Clone();
}
/// <summary>
@ -150,10 +175,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int Dimension
{
get
{
return _alpha.Length;
}
get { return _alpha.Length; }
}
/// <summary>
@ -161,26 +183,16 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double[] Alpha
{
get
{
return _alpha;
}
set
{
SetParameters(value);
}
get { return _alpha; }
set { SetParameters(value); }
}
/// <summary>
/// Gets the sum of the Dirichlet parameters.
/// </summary>
private double AlphaSum
double AlphaSum
{
get
{
return _alpha.Sum();
}
get { return _alpha.Sum(); }
}
/// <summary>
@ -194,7 +206,7 @@ namespace MathNet.Numerics.Distributions
var parm = new double[Dimension];
for (var i = 0; i < Dimension; i++)
{
parm[i] = _alpha[i] / sum;
parm[i] = _alpha[i]/sum;
}
return parm;
@ -212,7 +224,7 @@ namespace MathNet.Numerics.Distributions
var v = new double[_alpha.Length];
for (var i = 0; i < _alpha.Length; i++)
{
v[i] = _alpha[i] * (s - _alpha[i]) / (s * s * (s + 1.0));
v[i] = _alpha[i]*(s - _alpha[i])/(s*s*(s + 1.0));
}
return v;
@ -226,8 +238,8 @@ namespace MathNet.Numerics.Distributions
{
get
{
var num = _alpha.Sum(t => (t - 1) * SpecialFunctions.DiGamma(t));
return SpecialFunctions.GammaLn(AlphaSum) + ((AlphaSum - Dimension) * SpecialFunctions.DiGamma(AlphaSum)) - num;
var num = _alpha.Sum(t => (t - 1)*SpecialFunctions.DiGamma(t));
return SpecialFunctions.GammaLn(AlphaSum) + ((AlphaSum - Dimension)*SpecialFunctions.DiGamma(AlphaSum)) - num;
}
}
@ -272,7 +284,7 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
term += (_alpha[i] - 1.0) * Math.Log(xi) - SpecialFunctions.GammaLn(_alpha[i]);
term += (_alpha[i] - 1.0)*Math.Log(xi) - SpecialFunctions.GammaLn(_alpha[i]);
sumxi += xi;
sumalpha += _alpha[i];
}
@ -285,7 +297,7 @@ namespace MathNet.Numerics.Distributions
return 0.0;
}
term += (_alpha[_alpha.Length - 1] - 1.0) * Math.Log(1.0 - sumxi) - SpecialFunctions.GammaLn(_alpha[_alpha.Length - 1]);
term += (_alpha[_alpha.Length - 1] - 1.0)*Math.Log(1.0 - sumxi) - SpecialFunctions.GammaLn(_alpha[_alpha.Length - 1]);
sumalpha += _alpha[_alpha.Length - 1];
}
else if (!sumxi.AlmostEqualInDecimalPlaces(1.0, 8))
@ -301,11 +313,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public Random RandomSource
{
get
{
return _random;
}
get { return _random; }
set
{
if (value == null)
@ -334,7 +342,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a sample from the distribution.</returns>
public static double[] Sample(Random rnd, double[] alpha)
{
if (Control.CheckDistributionParameters && ! IsValidParameterSet(alpha))
if (Control.CheckDistributionParameters && !IsValidParameterSet(alpha))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}

92
src/Numerics/Distributions/Multivariate/InverseWishart.cs

@ -47,36 +47,44 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// The degrees of freedom for the inverse Wishart distribution.
/// </summary>
private double _nu;
double _nu;
/// <summary>
/// The scale matrix for the inverse Wishart distribution.
/// </summary>
private Matrix<double> _s;
Matrix<double> _s;
/// <summary>
/// Caches the Cholesky factorization of the scale matrix.
/// </summary>
private Cholesky<double> _chol;
Cholesky<double> _chol;
/// <summary>
/// The distribution's random number generator.
/// </summary>
private Random _random;
Random _random;
/// <summary>
/// Initializes a new instance of the <see cref="InverseWishart"/> class.
/// </summary>
/// <param name="nu">
/// The degrees of freedom for the inverse Wishart distribution.
/// </param>
/// <param name="s">
/// The scale matrix for the inverse Wishart distribution.
/// </param>
/// <param name="nu">The degrees of freedom for the inverse Wishart distribution.</param>
/// <param name="s">The scale matrix for the inverse Wishart distribution.</param>
public InverseWishart(double nu, Matrix<double> s)
{
_random = new Random();
SetParameters(nu, s);
}
/// <summary>
/// Initializes a new instance of the <see cref="InverseWishart"/> class.
/// </summary>
/// <param name="nu">The degrees of freedom for the inverse Wishart distribution.</param>
/// <param name="s">The scale matrix for the inverse Wishart distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public InverseWishart(double nu, Matrix<double> s, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(nu, s);
RandomSource = new Random();
}
/// <summary>
@ -94,7 +102,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="nu">The degrees of freedom for the Wishart distribution.</param>
/// <param name="s">The scale matrix for the Wishart distribution.</param>
/// <exception cref="ArgumentOutOfRangeException">When the parameters don't pass the <see cref="IsValidParameterSet"/> function.</exception>
private void SetParameters(double nu, Matrix<double> s)
void SetParameters(double nu, Matrix<double> s)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(nu, s))
{
@ -112,7 +120,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="nu">The degrees of freedom for the Wishart distribution.</param>
/// <param name="s">The scale matrix for the Wishart distribution.</param>
/// <returns><c>true</c> when the parameters are valid, <c>false</c> otherwise.</returns>
private static bool IsValidParameterSet(double nu, Matrix<double> s)
static bool IsValidParameterSet(double nu, Matrix<double> s)
{
if (s.RowCount != s.ColumnCount)
{
@ -140,15 +148,8 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Nu
{
get
{
return _nu;
}
set
{
SetParameters(value, _s);
}
get { return _nu; }
set { SetParameters(value, _s); }
}
/// <summary>
@ -156,15 +157,8 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public Matrix<double> S
{
get
{
return _s;
}
set
{
SetParameters(_nu, value);
}
get { return _s; }
set { SetParameters(_nu, value); }
}
/// <summary>
@ -172,11 +166,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public Random RandomSource
{
get
{
return _random;
}
get { return _random; }
set
{
if (value == null)
@ -194,10 +184,7 @@ namespace MathNet.Numerics.Distributions
/// <value>The mean of the distribution.</value>
public Matrix<double> Mean
{
get
{
return _s * (1.0 / (_nu - _s.RowCount - 1.0));
}
get { return _s*(1.0/(_nu - _s.RowCount - 1.0)); }
}
/// <summary>
@ -207,10 +194,7 @@ namespace MathNet.Numerics.Distributions
/// <remarks>A. O'Hagan, and J. J. Forster (2004). Kendall's Advanced Theory of Statistics: Bayesian Inference. 2B (2 ed.). Arnold. ISBN 0-340-80752-0.</remarks>
public Matrix<double> Mode
{
get
{
return _s * (1.0 / (_nu + _s.RowCount + 1.0));
}
get { return _s*(1.0/(_nu + _s.RowCount + 1.0)); }
}
/// <summary>
@ -227,9 +211,9 @@ namespace MathNet.Numerics.Distributions
{
for (var j = 0; j < res.ColumnCount; j++)
{
var num1 = ((_nu - _s.RowCount + 1) * _s.At(i, j) * _s.At(i, j)) + ((_nu - _s.RowCount - 1) * _s.At(i, i) * _s.At(j, j));
var num2 = (_nu - _s.RowCount) * (_nu - _s.RowCount - 1) * (_nu - _s.RowCount - 1) * (_nu - _s.RowCount - 3);
res.At(i, j, num1 / num2);
var num1 = ((_nu - _s.RowCount + 1)*_s.At(i, j)*_s.At(i, j)) + ((_nu - _s.RowCount - 1)*_s.At(i, i)*_s.At(j, j));
var num2 = (_nu - _s.RowCount)*(_nu - _s.RowCount - 1)*(_nu - _s.RowCount - 1)*(_nu - _s.RowCount - 3);
res.At(i, j, num1/num2);
}
}
@ -257,17 +241,17 @@ namespace MathNet.Numerics.Distributions
var sXi = chol.Solve(S);
// Compute the multivariate Gamma function.
var gp = Math.Pow(Constants.Pi, p * (p - 1.0) / 4.0);
var gp = Math.Pow(Constants.Pi, p*(p - 1.0)/4.0);
for (var j = 1; j <= p; j++)
{
gp *= SpecialFunctions.Gamma((_nu + 1.0 - j) / 2.0);
gp *= SpecialFunctions.Gamma((_nu + 1.0 - j)/2.0);
}
return Math.Pow(dX, -(_nu + p + 1.0) / 2.0)
* Math.Exp(-0.5 * sXi.Trace())
* Math.Pow(_chol.Determinant, _nu / 2.0)
/ Math.Pow(2.0, _nu * p / 2.0)
/ gp;
return Math.Pow(dX, -(_nu + p + 1.0)/2.0)
*Math.Exp(-0.5*sXi.Trace())
*Math.Pow(_chol.Determinant, _nu/2.0)
/Math.Pow(2.0, _nu*p/2.0)
/gp;
}
/// <summary>

101
src/Numerics/Distributions/Multivariate/MatrixNormal.cs

@ -48,42 +48,48 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// The mean of the matrix normal distribution.
/// </summary>
private Matrix<double> _m;
Matrix<double> _m;
/// <summary>
/// The covariance matrix for the rows.
/// </summary>
private Matrix<double> _v;
Matrix<double> _v;
/// <summary>
/// The covariance matrix for the columns.
/// </summary>
private Matrix<double> _k;
Matrix<double> _k;
/// <summary>
/// The distribution's random number generator.
/// </summary>
private Random _random;
Random _random;
/// <summary>
/// Initializes a new instance of the <see cref="MatrixNormal"/> class.
/// </summary>
/// <param name="m">
/// The mean of the matrix normal.
/// </param>
/// <param name="v">
/// The covariance matrix for the rows.
/// </param>
/// <param name="k">
/// The covariance matrix for the columns.
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// If the dimensions of the mean and two covariance matrices don't match.
/// </exception>
/// <param name="m">The mean of the matrix normal.</param>
/// <param name="v">The covariance matrix for the rows.</param>
/// <param name="k">The covariance matrix for the columns.</param>
/// <exception cref="ArgumentOutOfRangeException">If the dimensions of the mean and two covariance matrices don't match.</exception>
public MatrixNormal(Matrix<double> m, Matrix<double> v, Matrix<double> k)
{
_random = new Random();
SetParameters(m, v, k);
}
/// <summary>
/// Initializes a new instance of the <see cref="MatrixNormal"/> class.
/// </summary>
/// <param name="m">The mean of the matrix normal.</param>
/// <param name="v">The covariance matrix for the rows.</param>
/// <param name="k">The covariance matrix for the columns.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentOutOfRangeException">If the dimensions of the mean and two covariance matrices don't match.</exception>
public MatrixNormal(Matrix<double> m, Matrix<double> v, Matrix<double> k, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(m, v, k);
RandomSource = new Random();
}
/// <summary>
@ -103,15 +109,8 @@ namespace MathNet.Numerics.Distributions
/// <value>The mean of the distribution.</value>
public Matrix<double> Mean
{
get
{
return _m;
}
set
{
SetParameters(value, _v, _k);
}
get { return _m; }
set { SetParameters(value, _v, _k); }
}
/// <summary>
@ -120,15 +119,8 @@ namespace MathNet.Numerics.Distributions
/// <value>The row covariance.</value>
public Matrix<double> RowCovariance
{
get
{
return _v;
}
set
{
SetParameters(_m, value, _k);
}
get { return _v; }
set { SetParameters(_m, value, _k); }
}
/// <summary>
@ -137,15 +129,8 @@ namespace MathNet.Numerics.Distributions
/// <value>The column covariance.</value>
public Matrix<double> ColumnCovariance
{
get
{
return _k;
}
set
{
SetParameters(_m, _v, value);
}
get { return _k; }
set { SetParameters(_m, _v, value); }
}
/// <summary>
@ -155,7 +140,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="v">The covariance matrix for the rows.</param>
/// <param name="k">The covariance matrix for the columns.</param>
/// <exception cref="ArgumentOutOfRangeException">When the parameters don't pass the <see cref="IsValidParameterSet"/> function.</exception>
private void SetParameters(Matrix<double> m, Matrix<double> v, Matrix<double> k)
void SetParameters(Matrix<double> m, Matrix<double> v, Matrix<double> k)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(m, v, k))
{
@ -174,7 +159,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="v">The covariance matrix for the rows.</param>
/// <param name="k">The covariance matrix for the columns.</param>
/// <returns><c>true</c> when the parameters are valid, <c>false</c> otherwise.</returns>
private static bool IsValidParameterSet(Matrix<double> m, Matrix<double> v, Matrix<double> k)
static bool IsValidParameterSet(Matrix<double> m, Matrix<double> v, Matrix<double> k)
{
var n = m.RowCount;
var p = m.ColumnCount;
@ -212,11 +197,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public Random RandomSource
{
get
{
return _random;
}
get { return _random; }
set
{
if (value == null)
@ -245,10 +226,10 @@ namespace MathNet.Numerics.Distributions
var cholV = Cholesky<double>.Create(_v);
var cholK = Cholesky<double>.Create(_k);
return Math.Exp(-0.5 * cholV.Solve(a.Transpose() * cholK.Solve(a)).Trace())
/ Math.Pow(2.0 * Constants.Pi, x.RowCount * x.ColumnCount / 2.0)
/ Math.Pow(cholV.Determinant, x.RowCount / 2.0)
/ Math.Pow(cholK.Determinant, x.ColumnCount / 2.0);
return Math.Exp(-0.5*cholV.Solve(a.Transpose()*cholK.Solve(a)).Trace())
/Math.Pow(2.0*Constants.Pi, x.RowCount*x.ColumnCount/2.0)
/Math.Pow(cholV.Determinant, x.RowCount/2.0)
/Math.Pow(cholK.Determinant, x.ColumnCount/2.0);
}
/// <summary>
@ -283,7 +264,7 @@ namespace MathNet.Numerics.Distributions
var vki = v.KroneckerProduct(k.Inverse());
// Sample a vector valued random variable with VKi as the covariance.
var vector = SampleVectorNormal(rnd, new DenseVector(n * p), vki);
var vector = SampleVectorNormal(rnd, new DenseVector(n*p), vki);
// Unstack the vector v and add the mean.
var r = m.Clone();
@ -291,7 +272,7 @@ namespace MathNet.Numerics.Distributions
{
for (var j = 0; j < p; j++)
{
r.At(i, j, r.At(i, j) + vector[(j * n) + i]);
r.At(i, j, r.At(i, j) + vector[(j*n) + i]);
}
}
@ -305,7 +286,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="mean">The mean of the vector normal distribution.</param>
/// <param name="covariance">The covariance matrix of the vector normal distribution.</param>
/// <returns>a sequence of samples from defined distribution.</returns>
private static Vector<double> SampleVectorNormal(Random rnd, Vector<double> mean, Matrix<double> covariance)
static Vector<double> SampleVectorNormal(Random rnd, Vector<double> mean, Matrix<double> covariance)
{
var chol = Cholesky<double>.Create(covariance);
return SampleVectorNormal(rnd, mean, chol);
@ -318,7 +299,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="mean">The mean of the vector normal distribution.</param>
/// <param name="cholesky">The Cholesky factorization of the covariance matrix.</param>
/// <returns>a sequence of samples from defined distribution.</returns>
private static Vector<double> SampleVectorNormal(Random rnd, Vector<double> mean, Cholesky<double> cholesky)
static Vector<double> SampleVectorNormal(Random rnd, Vector<double> mean, Cholesky<double> cholesky)
{
var count = mean.Count;
@ -335,7 +316,7 @@ namespace MathNet.Numerics.Distributions
}
// Return the transformed variable.
return mean + (cholesky.Factor * v);
return mean + (cholesky.Factor*v);
}
}
}

76
src/Numerics/Distributions/Multivariate/Multinomial.cs

@ -51,17 +51,17 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// Stores the normalized multinomial probabilities.
/// </summary>
private double[] _p;
double[] _p;
/// <summary>
/// The number of trials.
/// </summary>
private int _n;
int _n;
/// <summary>
/// The distribution's random number generator.
/// </summary>
private Random _random;
Random _random;
/// <summary>
/// Initializes a new instance of the Multinomial class.
@ -73,8 +73,23 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="n"/> is negative.</exception>
public Multinomial(double[] p, int n)
{
_random = new Random();
SetParameters(p, n);
}
/// <summary>
/// Initializes a new instance of the Multinomial class.
/// </summary>
/// <param name="p">An array of nonnegative ratios: this array does not need to be normalized
/// as this is often impossible using floating point arithmetic.</param>
/// <param name="n">The number of trials.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// <exception cref="ArgumentOutOfRangeException">If any of the probabilities are negative or do not sum to one.</exception>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="n"/> is negative.</exception>
public Multinomial(double[] p, int n, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(p, n);
RandomSource = new Random();
}
/// <summary>
@ -83,7 +98,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
/// <param name="h">Histogram instance</param>
/// <param name="n">The number of trials.</param>
/// <exception cref="ArgumentOutOfRangeException">If any of the probabilities are negative or do not sum to one.</exception>
/// <exception cref="ArgumentOutOfRangeException">If any of the probabilities are negative or do not sum to one.</exception>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="n"/> is negative.</exception>
public Multinomial(Histogram h, int n)
{
@ -122,7 +137,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="n">The number of trials.</param>
/// <returns>If any of the probabilities are negative returns <c>false</c>,
/// if the sum of parameters is 0.0, or if the number of trials is negative; otherwise <c>true</c>.</returns>
private static bool IsValidParameterSet(IEnumerable<double> p, int n)
static bool IsValidParameterSet(IEnumerable<double> p, int n)
{
var sum = 0.0;
foreach (var t in p)
@ -150,14 +165,14 @@ namespace MathNet.Numerics.Distributions
/// as this is often impossible using floating point arithmetic.</param>
/// <param name="n">The number of trials.</param>
/// <exception cref="ArgumentOutOfRangeException">When the parameters don't pass the <see cref="IsValidParameterSet"/> function.</exception>
private void SetParameters(double[] p, int n)
void SetParameters(double[] p, int n)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(p, n))
{
throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
}
_p = (double[])p.Clone();
_p = (double[]) p.Clone();
_n = n;
}
@ -166,15 +181,8 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double[] P
{
get
{
return (double[])_p.Clone();
}
set
{
SetParameters(value, _n);
}
get { return (double[]) _p.Clone(); }
set { SetParameters(value, _n); }
}
/// <summary>
@ -182,15 +190,8 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public int N
{
get
{
return _n;
}
set
{
SetParameters(_p, value);
}
get { return _n; }
set { SetParameters(_p, value); }
}
/// <summary>
@ -198,11 +199,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public Random RandomSource
{
get
{
return _random;
}
get { return _random; }
set
{
if (value == null)
@ -219,10 +216,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public Vector<double> Mean
{
get
{
return _n * (DenseVector)P;
}
get { return _n*(DenseVector) P; }
}
/// <summary>
@ -233,10 +227,10 @@ namespace MathNet.Numerics.Distributions
get
{
// Do not use _p, because operations below will modify _p array. Use P or _p.Clone().
var res = (DenseVector)P;
var res = (DenseVector) P;
for (var i = 0; i < res.Count; i++)
{
res[i] *= _n * (1 - res[i]);
res[i] *= _n*(1 - res[i]);
}
return res;
@ -251,10 +245,10 @@ namespace MathNet.Numerics.Distributions
get
{
// Do not use _p, because operations below will modify _p array. Use P or _p.Clone().
var res = (DenseVector)P;
var res = (DenseVector) P;
for (var i = 0; i < res.Count; i++)
{
res[i] = (1.0 - (2.0 * res[i])) / Math.Sqrt(_n * (1.0 - res[i]) * res[i]);
res[i] = (1.0 - (2.0*res[i]))/Math.Sqrt(_n*(1.0 - res[i])*res[i]);
}
return res;
@ -289,7 +283,7 @@ namespace MathNet.Numerics.Distributions
num *= Math.Pow(_p[i], x[i]);
}
return coef * num;
return coef*num;
}
return 0.0;
@ -317,7 +311,7 @@ namespace MathNet.Numerics.Distributions
if (x.Sum() == _n)
{
var coef = Math.Log(SpecialFunctions.Multinomial(_n, x));
var num = x.Select((t, i) => t * Math.Log(_p[i])).Sum();
var num = x.Select((t, i) => t*Math.Log(_p[i])).Sum();
return coef + num;
}

164
src/Numerics/Distributions/Multivariate/NormalGamma.cs

@ -39,22 +39,18 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// The mean value.
/// </summary>
private double _mean;
double _mean;
/// <summary>
/// The precision value.
/// </summary>
private double _precision;
double _precision;
/// <summary>
/// Initializes a new instance of the <see cref="MeanPrecisionPair"/> struct.
/// </summary>
/// <param name="m">
/// The mean of the pair.
/// </param>
/// <param name="p">
/// The precision of the pair.
/// </param>
/// <param name="m">The mean of the pair.</param>
/// <param name="p">The precision of the pair.</param>
public MeanPrecisionPair(double m, double p)
{
_mean = m;
@ -66,15 +62,9 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Mean
{
get
{
return _mean;
}
get { return _mean; }
set
{
_mean = value;
}
set { _mean = value; }
}
/// <summary>
@ -82,15 +72,9 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Precision
{
get
{
return _precision;
}
get { return _precision; }
set
{
_precision = value;
}
set { _precision = value; }
}
}
@ -116,47 +100,53 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// The location of the mean.
/// </summary>
private double _meanLocation;
double _meanLocation;
/// <summary>
/// The scale of the mean.
/// </summary>
private double _meanScale;
double _meanScale;
/// <summary>
/// The shape of the precision.
/// </summary>
private double _precisionShape;
double _precisionShape;
/// <summary>
/// The inverse scale of the precision.
/// </summary>
private double _precisionInvScale;
double _precisionInvScale;
/// <summary>
/// The distribution's random number generator.
/// </summary>
private Random _random;
Random _random;
/// <summary>
/// Initializes a new instance of the <see cref="NormalGamma"/> class.
/// </summary>
/// <param name="meanLocation">
/// The location of the mean.
/// </param>
/// <param name="meanScale">
/// The scale of the mean.
/// </param>
/// <param name="precisionShape">
/// The shape of the precision.
/// </param>
/// <param name="precisionInverseScale">
/// The inverse scale of the precision.
/// </param>
/// <param name="meanLocation">The location of the mean.</param>
/// <param name="meanScale">The scale of the mean.</param>
/// <param name="precisionShape">The shape of the precision.</param>
/// <param name="precisionInverseScale">The inverse scale of the precision.</param>
public NormalGamma(double meanLocation, double meanScale, double precisionShape, double precisionInverseScale)
{
SetParameters(meanLocation, meanScale, precisionShape, precisionInverseScale);
_random = new Random();
SetParameters(meanLocation, meanScale, precisionShape, precisionInverseScale);
}
/// <summary>
/// Initializes a new instance of the <see cref="NormalGamma"/> class.
/// </summary>
/// <param name="meanLocation">The location of the mean.</param>
/// <param name="meanScale">The scale of the mean.</param>
/// <param name="precisionShape">The shape of the precision.</param>
/// <param name="precisionInverseScale">The inverse scale of the precision.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public NormalGamma(double meanLocation, double meanScale, double precisionShape, double precisionInverseScale, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(meanLocation, meanScale, precisionShape, precisionInverseScale);
}
/// <summary>
@ -167,7 +157,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="precShape">The shape of the precision.</param>
/// <param name="precInvScale">The inverse scale of the precision.</param>
/// <returns><c>true</c> when the parameters are valid, <c>false</c> otherwise.</returns>
private static bool IsValidParameterSet(double meanLocation, double meanScale, double precShape, double precInvScale)
static bool IsValidParameterSet(double meanLocation, double meanScale, double precShape, double precInvScale)
{
if (meanScale <= 0.0 || precShape <= 0.0 || precInvScale <= 0.0
|| Double.IsNaN(meanLocation) || Double.IsNaN(meanScale) || Double.IsNaN(precShape)
@ -187,7 +177,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="precShape">The shape of the precision.</param>
/// <param name="precInvScale">The inverse scale of the precision.</param>
/// <exception cref="ArgumentOutOfRangeException">When the parameters don't pass the <see cref="IsValidParameterSet"/> function.</exception>
private void SetParameters(double meanLocation, double meanScale, double precShape, double precInvScale)
void SetParameters(double meanLocation, double meanScale, double precShape, double precInvScale)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(meanLocation, meanScale, precShape, precInvScale))
{
@ -207,7 +197,7 @@ namespace MathNet.Numerics.Distributions
public override string ToString()
{
return "NormalGamma(Mean Location = " + _meanLocation + ", Mean Scale = " + _meanScale +
", Precision Shape = " + _precisionShape + ", Precision Inverse Scale = " + _precisionInvScale + ")";
", Precision Shape = " + _precisionShape + ", Precision Inverse Scale = " + _precisionInvScale + ")";
}
/// <summary>
@ -215,15 +205,8 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double MeanLocation
{
get
{
return _meanLocation;
}
set
{
SetParameters(value, _meanScale, _precisionShape, _precisionInvScale);
}
get { return _meanLocation; }
set { SetParameters(value, _meanScale, _precisionShape, _precisionInvScale); }
}
/// <summary>
@ -231,15 +214,8 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double MeanScale
{
get
{
return _meanScale;
}
set
{
SetParameters(_meanLocation, value, _precisionShape, _precisionInvScale);
}
get { return _meanScale; }
set { SetParameters(_meanLocation, value, _precisionShape, _precisionInvScale); }
}
/// <summary>
@ -247,15 +223,8 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double PrecisionShape
{
get
{
return _precisionShape;
}
set
{
SetParameters(_meanLocation, _meanScale, value, _precisionInvScale);
}
get { return _precisionShape; }
set { SetParameters(_meanLocation, _meanScale, value, _precisionInvScale); }
}
/// <summary>
@ -263,15 +232,8 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double PrecisionInverseScale
{
get
{
return _precisionInvScale;
}
set
{
SetParameters(_meanLocation, _meanScale, _precisionShape, value);
}
get { return _precisionInvScale; }
set { SetParameters(_meanLocation, _meanScale, _precisionShape, value); }
}
/// <summary>
@ -279,11 +241,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public Random RandomSource
{
get
{
return _random;
}
get { return _random; }
set
{
if (value == null)
@ -303,10 +261,10 @@ namespace MathNet.Numerics.Distributions
{
if (Double.IsPositiveInfinity(_precisionInvScale))
{
return new StudentT(_meanLocation, 1.0 / (_meanScale * _precisionShape), Double.PositiveInfinity);
return new StudentT(_meanLocation, 1.0/(_meanScale*_precisionShape), Double.PositiveInfinity);
}
return new StudentT(_meanLocation, Math.Sqrt(_precisionInvScale / (_meanScale * _precisionShape)), 2.0 * _precisionShape);
return new StudentT(_meanLocation, Math.Sqrt(_precisionInvScale/(_meanScale*_precisionShape)), 2.0*_precisionShape);
}
/// <summary>
@ -324,10 +282,7 @@ namespace MathNet.Numerics.Distributions
/// <value>The mean of the distribution.</value>
public MeanPrecisionPair Mean
{
get
{
return Double.IsPositiveInfinity(_precisionInvScale) ? new MeanPrecisionPair(_meanLocation, _precisionShape) : new MeanPrecisionPair(_meanLocation, _precisionShape / _precisionInvScale);
}
get { return Double.IsPositiveInfinity(_precisionInvScale) ? new MeanPrecisionPair(_meanLocation, _precisionShape) : new MeanPrecisionPair(_meanLocation, _precisionShape/_precisionInvScale); }
}
/// <summary>
@ -336,10 +291,7 @@ namespace MathNet.Numerics.Distributions
/// <value>The mean of the distribution.</value>
public MeanPrecisionPair Variance
{
get
{
return new MeanPrecisionPair(_precisionInvScale / (_meanScale * (_precisionShape - 1)), _precisionShape / Math.Sqrt(_precisionInvScale));
}
get { return new MeanPrecisionPair(_precisionInvScale/(_meanScale*(_precisionShape - 1)), _precisionShape/Math.Sqrt(_precisionInvScale)); }
}
/// <summary>
@ -377,9 +329,9 @@ namespace MathNet.Numerics.Distributions
// double e = -0.5 * prec * (mean - _meanLocation) * (mean - _meanLocation) - prec * _precisionInvScale;
// return Math.Pow(prec * _precisionInvScale, _precisionShape) * Math.Exp(e) / (Constants.Sqrt2Pi * Math.Sqrt(prec) * SpecialFunctions.Gamma(_precisionShape));
double e = -(0.5 * prec * _meanScale * (mean - _meanLocation) * (mean - _meanLocation)) - (prec * _precisionInvScale);
return Math.Pow(prec * _precisionInvScale, _precisionShape) * Math.Exp(e) * Math.Sqrt(_meanScale)
/ (Constants.Sqrt2Pi * Math.Sqrt(prec) * SpecialFunctions.Gamma(_precisionShape));
double e = -(0.5*prec*_meanScale*(mean - _meanLocation)*(mean - _meanLocation)) - (prec*_precisionInvScale);
return Math.Pow(prec*_precisionInvScale, _precisionShape)*Math.Exp(e)*Math.Sqrt(_meanScale)
/(Constants.Sqrt2Pi*Math.Sqrt(prec)*SpecialFunctions.Gamma(_precisionShape));
}
/// <summary>
@ -404,12 +356,12 @@ namespace MathNet.Numerics.Distributions
{
throw new NotSupportedException();
}
if (Double.IsPositiveInfinity(_precisionInvScale))
{
throw new NotSupportedException();
}
if (_meanScale <= 0.0)
{
throw new NotSupportedException();
@ -417,8 +369,8 @@ namespace MathNet.Numerics.Distributions
// double e = -0.5 * prec * (mean - _meanLocation) * (mean - _meanLocation) - prec * _precisionInvScale;
// return (_precisionShape - 0.5) * Math.Log(prec) + _precisionShape * Math.Log(_precisionInvScale) + e - Constants.LogSqrt2Pi - SpecialFunctions.GammaLn(_precisionShape);
double e = -(0.5 * prec * _meanScale * (mean - _meanLocation) * (mean - _meanLocation)) - (prec * _precisionInvScale);
return ((_precisionShape - 0.5) * Math.Log(prec)) + (_precisionShape * Math.Log(_precisionInvScale)) - (0.5 * Math.Log(_meanScale)) + e - Constants.LogSqrt2Pi - SpecialFunctions.GammaLn(_precisionShape);
double e = -(0.5*prec*_meanScale*(mean - _meanLocation)*(mean - _meanLocation)) - (prec*_precisionInvScale);
return ((_precisionShape - 0.5)*Math.Log(prec)) + (_precisionShape*Math.Log(_precisionInvScale)) - (0.5*Math.Log(_meanScale)) + e - Constants.LogSqrt2Pi - SpecialFunctions.GammaLn(_precisionShape);
}
/// <summary>
@ -464,7 +416,7 @@ namespace MathNet.Numerics.Distributions
mp.Precision = Double.IsPositiveInfinity(precisionInverseScale) ? precisionShape : Gamma.Sample(rnd, precisionShape, precisionInverseScale);
// Sample the mean.
mp.Mean = meanScale == 0.0 ? meanLocation : Normal.Sample(rnd, meanLocation, Math.Sqrt(1.0 / (meanScale * mp.Precision)));
mp.Mean = meanScale == 0.0 ? meanLocation : Normal.Sample(rnd, meanLocation, Math.Sqrt(1.0/(meanScale*mp.Precision)));
return mp;
}
@ -493,7 +445,7 @@ namespace MathNet.Numerics.Distributions
mp.Precision = Double.IsPositiveInfinity(precisionInvScale) ? precisionShape : Gamma.Sample(rnd, precisionShape, precisionInvScale);
// Sample the mean.
mp.Mean = meanScale == 0.0 ? meanLocation : Normal.Sample(rnd, meanLocation, Math.Sqrt(1.0 / (meanScale * mp.Precision)));
mp.Mean = meanScale == 0.0 ? meanLocation : Normal.Sample(rnd, meanLocation, Math.Sqrt(1.0/(meanScale*mp.Precision)));
yield return mp;
}

92
src/Numerics/Distributions/Multivariate/Wishart.cs

@ -49,36 +49,44 @@ namespace MathNet.Numerics.Distributions
/// <summary>
/// The degrees of freedom for the Wishart distribution.
/// </summary>
private double _nu;
double _nu;
/// <summary>
/// The scale matrix for the Wishart distribution.
/// </summary>
private Matrix<double> _s;
Matrix<double> _s;
/// <summary>
/// Caches the Cholesky factorization of the scale matrix.
/// </summary>
private Cholesky<double> _chol;
Cholesky<double> _chol;
/// <summary>
/// The distribution's random number generator.
/// </summary>
private Random _random;
Random _random;
/// <summary>
/// Initializes a new instance of the <see cref="Wishart"/> class.
/// </summary>
/// <param name="nu">
/// The degrees of freedom for the Wishart distribution.
/// </param>
/// <param name="s">
/// The scale matrix for the Wishart distribution.
/// </param>
/// <param name="nu">The degrees of freedom for the Wishart distribution.</param>
/// <param name="s">The scale matrix for the Wishart distribution.</param>
public Wishart(double nu, Matrix<double> s)
{
_random = new Random();
SetParameters(nu, s);
}
/// <summary>
/// Initializes a new instance of the <see cref="Wishart"/> class.
/// </summary>
/// <param name="nu">The degrees of freedom for the Wishart distribution.</param>
/// <param name="s">The scale matrix for the Wishart distribution.</param>
/// <param name="randomSource">The random number generator which is used to draw random samples.</param>
public Wishart(double nu, Matrix<double> s, Random randomSource)
{
_random = randomSource ?? new Random();
SetParameters(nu, s);
RandomSource = new Random();
}
/// <summary>
@ -87,7 +95,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="nu">The degrees of freedom for the Wishart distribution.</param>
/// <param name="s">The scale matrix for the Wishart distribution.</param>
/// <exception cref="ArgumentOutOfRangeException">When the parameters don't pass the <see cref="IsValidParameterSet"/> function.</exception>
private void SetParameters(double nu, Matrix<double> s)
void SetParameters(double nu, Matrix<double> s)
{
if (Control.CheckDistributionParameters && !IsValidParameterSet(nu, s))
{
@ -105,7 +113,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="nu">The degrees of freedom for the Wishart distribution.</param>
/// <param name="s">The scale matrix for the Wishart distribution.</param>
/// <returns><c>true</c> when the parameters are valid, <c>false</c> otherwise.</returns>
private static bool IsValidParameterSet(double nu, Matrix<double> s)
static bool IsValidParameterSet(double nu, Matrix<double> s)
{
if (s.RowCount != s.ColumnCount)
{
@ -133,15 +141,8 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public double Nu
{
get
{
return _nu;
}
set
{
SetParameters(value, _s);
}
get { return _nu; }
set { SetParameters(value, _s); }
}
/// <summary>
@ -149,15 +150,8 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public Matrix<double> S
{
get
{
return _s;
}
set
{
SetParameters(_nu, value);
}
get { return _s; }
set { SetParameters(_nu, value); }
}
/// <summary>
@ -174,11 +168,7 @@ namespace MathNet.Numerics.Distributions
/// </summary>
public Random RandomSource
{
get
{
return _random;
}
get { return _random; }
set
{
if (value == null)
@ -196,10 +186,7 @@ namespace MathNet.Numerics.Distributions
/// <value>The mean of the distribution.</value>
public Matrix<double> Mean
{
get
{
return _nu * _s;
}
get { return _nu*_s; }
}
/// <summary>
@ -208,10 +195,7 @@ namespace MathNet.Numerics.Distributions
/// <value>The mode of the distribution.</value>
public Matrix<double> Mode
{
get
{
return (_nu - _s.RowCount - 1.0) * _s;
}
get { return (_nu - _s.RowCount - 1.0)*_s; }
}
/// <summary>
@ -227,7 +211,7 @@ namespace MathNet.Numerics.Distributions
{
for (var j = 0; j < res.ColumnCount; j++)
{
res.At(i, j, _nu * ((_s.At(i, j) * _s.At(i, j)) + (_s.At(i, i) * _s.At(j, j))));
res.At(i, j, _nu*((_s.At(i, j)*_s.At(i, j)) + (_s.At(i, i)*_s.At(j, j))));
}
}
@ -254,17 +238,17 @@ namespace MathNet.Numerics.Distributions
var siX = _chol.Solve(x);
// Compute the multivariate Gamma function.
var gp = Math.Pow(Constants.Pi, p * (p - 1.0) / 4.0);
var gp = Math.Pow(Constants.Pi, p*(p - 1.0)/4.0);
for (var j = 1; j <= p; j++)
{
gp *= SpecialFunctions.Gamma((_nu + 1.0 - j) / 2.0);
gp *= SpecialFunctions.Gamma((_nu + 1.0 - j)/2.0);
}
return Math.Pow(dX, (_nu - p - 1.0) / 2.0)
* Math.Exp(-0.5 * siX.Trace())
/ Math.Pow(2.0, _nu * p / 2.0)
/ Math.Pow(_chol.Determinant, _nu / 2.0)
/ gp;
return Math.Pow(dX, (_nu - p - 1.0)/2.0)
*Math.Exp(-0.5*siX.Trace())
/Math.Pow(2.0, _nu*p/2.0)
/Math.Pow(_chol.Determinant, _nu/2.0)
/gp;
}
/// <summary>
@ -307,7 +291,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="s">The S parameter to use.</param>
/// <param name="chol">The cholesky decomposition to use.</param>
/// <returns>a random number from the distribution.</returns>
private static Matrix<double> DoSample(Random rnd, double nu, Matrix<double> s, Cholesky<double> chol)
static Matrix<double> DoSample(Random rnd, double nu, Matrix<double> s, Cholesky<double> chol)
{
var count = s.RowCount;
@ -328,7 +312,7 @@ namespace MathNet.Numerics.Distributions
}
var factor = chol.Factor;
return factor * a * a.Transpose() * factor.Transpose();
return factor*a*a.Transpose()*factor.Transpose();
}
}
}

54
src/Numerics/IPrecisionSupport.cs

@ -1,54 +0,0 @@
// <copyright file="IPrecisionSupport.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2010 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics
{
/// <summary>
/// Support Interface for Precision Operations (like AlmostEquals).
/// </summary>
/// <typeparam name="T">Type of the implementing class.</typeparam>
public interface IPrecisionSupport<in T>
{
/// <summary>
/// Returns a Norm of a value of this type, which is appropriate for measuring how
/// close this value is to zero.
/// </summary>
/// <returns>A norm of this value.</returns>
double Norm();
/// <summary>
/// Returns a Norm of the difference of two values of this type, which is
/// appropriate for measuring how close together these two values are.
/// </summary>
/// <param name="otherValue">The value to compare with.</param>
/// <returns>A norm of the difference between this and the other value.</returns>
double NormOfDifference(T otherValue);
}
}

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

@ -28,6 +28,8 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.Threading;
namespace MathNet.Numerics.LinearAlgebra.Complex
{
using Algorithms.LinearAlgebra;
@ -588,6 +590,24 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
}
/// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary>
/// <param name="divisor">The scalar to divide the matrix with.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(Complex divisor, Matrix<Complex> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoDivide(divisor, result);
}
else
{
Control.LinearAlgebraProvider.ScaleArray(1.0/divisor, _values, denseResult._values);
}
}
/// <summary>
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
/// </summary>
@ -611,16 +631,16 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<Complex> other, Matrix<Complex> result)
protected override void DoPointwiseDivide(Matrix<Complex> divisor, Matrix<Complex> result)
{
var denseOther = other as DenseMatrix;
var denseOther = divisor as DenseMatrix;
var denseResult = result as DenseMatrix;
if (denseOther == null || denseResult == null)
{
base.DoPointwiseDivide(other, result);
base.DoPointwiseDivide(divisor, result);
}
else
{
@ -628,6 +648,30 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
}
/// <summary>
/// Add a scalar to each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(Complex scalar, Matrix<Complex> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoAdd(scalar, result);
return;
}
CommonParallel.For(0, _values.Length, 4096, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] = _values[i] + scalar;
}
});
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>
@ -649,6 +693,30 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
}
/// <summary>
/// Subtracts a scalar from each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to subtract.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(Complex scalar, Matrix<Complex> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoSubtract(scalar, result);
return;
}
CommonParallel.For(0, _values.Length, 4096, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] = _values[i] - scalar;
}
});
}
/// <summary>
/// Subtracts another matrix from this matrix.
/// </summary>

122
src/Numerics/LinearAlgebra/Complex/DenseVector.cs

@ -434,14 +434,33 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Computes the dot product between this vector and another vector.
/// </summary>
/// <param name="other">The other vector to add.</param>
/// <returns>s
/// The result of the addition.</returns>
/// <param name="other">The other vector.</param>
/// <returns>The sum of a[i]*b[i] for all i.</returns>
protected override Complex DoDotProduct(Vector<Complex> other)
{
var denseVector = other as DenseVector;
return denseVector == null
? base.DoDotProduct(other)
: Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
}
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
/// <summary>
/// Computes the dot product between the conjugate of this vector and another vector.
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>The sum of conj(a[i])*b[i] for all i.</returns>
protected override Complex DoConjugateDotProduct(Vector<Complex> other)
{
var denseVector = other as DenseVector;
if (denseVector == null) return base.DoConjugateDotProduct(other);
// TODO: provide native zdotc routine
var dot = Complex.Zero;
for (var i = 0; i < _values.Length; i++)
{
dot += _values[i].Conjugate()*denseVector._values[i];
}
return dot;
}
/// <summary>
@ -580,31 +599,67 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override Complex Sum()
{
var sum = Complex.Zero;
for (var i = 0; i < _length; i++)
{
sum += _values[i];
}
return sum;
}
/// <summary>
/// Computes the sum of the absolute value of the vector's elements.
/// Calculates the L1 norm of the vector, also known as Manhattan norm.
/// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns>
public override Complex SumMagnitudes()
/// <returns>The sum of the absolute values.</returns>
public override Complex L1Norm()
{
var sum = Complex.Zero;
for (var i = 0; i < _length; i++)
{
sum += _values[i].Magnitude;
}
return sum;
}
/// <summary>
/// Calculates the L2 norm of the vector, also known as Euclidean norm.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override Complex L2Norm()
{
// TODO: native provider
return _values.Aggregate(Complex.Zero, SpecialFunctions.Hypotenuse).Magnitude;
}
/// <summary>
/// Calculates the infinity norm of the vector.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override Complex InfinityNorm()
{
return CommonParallel.Aggregate(_values, (i, v) => v.Magnitude, Math.Max, 0d);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override Complex Norm(double p)
{
if (p < 0d) throw new ArgumentOutOfRangeException("p");
if (p == 1d) return L1Norm();
if (p == 2d) return L2Norm();
if (Double.IsPositiveInfinity(p)) return InfinityNorm();
var sum = 0d;
for (var i = 0; i < _length; i++)
{
sum += Math.Pow(_values[i].Magnitude, p);
}
return Math.Pow(sum, 1.0 / p);
}
/// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary>
@ -628,17 +683,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise divide this one by.</param>
/// <param name="divisor">The vector to pointwise divide this one by.</param>
/// <param name="result">The vector to store the result of the pointwise division.</param>
/// <remarks></remarks>
protected override void DoPointwiseDivide(Vector<Complex> other, Vector<Complex> result)
protected override void DoPointwiseDivide(Vector<Complex> divisor, Vector<Complex> result)
{
var denseOther = other as DenseVector;
var denseOther = divisor as DenseVector;
var denseResult = result as DenseVector;
if (denseOther == null || denseResult == null)
{
base.DoPointwiseDivide(other, result);
base.DoPointwiseDivide(divisor, result);
}
else
{
@ -693,43 +748,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return OuterProduct(this, v);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override Complex Norm(double p)
{
if (p < 0.0)
{
throw new ArgumentOutOfRangeException("p");
}
if (1.0 == p)
{
return SumMagnitudes();
}
if (2.0 == p)
{
return _values.Aggregate(Complex.Zero, SpecialFunctions.Hypotenuse).Magnitude;
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(_values, (i, v) => v.Magnitude, Math.Max, 0d);
}
var sum = 0.0;
for (var i = 0; i < _length; i++)
{
sum += Math.Pow(_values[i].Magnitude, p);
}
return Math.Pow(sum, 1.0 / p);
}
#region Parse Functions
/// <summary>

2
src/Numerics/LinearAlgebra/Complex/Factorization/UserGramSchmidt.cs

@ -74,7 +74,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
for (var k = 0; k < MatrixQ.ColumnCount; k++)
{
var norm = MatrixQ.Column(k).Norm(2);
var norm = MatrixQ.Column(k).L2Norm();
if (norm == 0.0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);

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

@ -129,6 +129,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return norm;
}
/// <summary>
/// Add a scalar to each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(Complex scalar, Matrix<Complex> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + scalar);
}
}
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>
@ -147,6 +163,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
}
/// <summary>
/// Subtracts a scalar from each element of the vector and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to subtract.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(Complex scalar, Matrix<Complex> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - scalar);
}
}
}
/// <summary>
/// Subtracts another matrix from this matrix.
/// </summary>
@ -225,11 +257,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary>
/// <param name="scalar">The scalar to divide the matrix with.</param>
/// <param name="divisor">The scalar to divide the matrix with.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(Complex scalar, Matrix<Complex> result)
protected override void DoDivide(Complex divisor, Matrix<Complex> result)
{
DoMultiply(1.0 / scalar, result);
DoMultiply(1.0 / divisor, result);
}
/// <summary>
/// Divides a scalar by each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="dividend">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivideByThis(Complex dividend, Matrix<Complex> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, dividend / At(i, j));
}
}
}
/// <summary>
@ -344,27 +392,47 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<Complex> other, Matrix<Complex> result)
protected override void DoPointwiseDivide(Matrix<Complex> divisor, Matrix<Complex> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j) / other.At(i, j));
result.At(i, j, At(i, j) / divisor.At(i, j));
}
}
}
/// <summary>
/// Pointwise modulus this matrix with another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="divisor">The pointwise denominator matrix to use</param>
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Matrix<Complex> divisor, Matrix<Complex> result)
{
throw new NotSupportedException();
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(Complex divisor, Matrix<Complex> result)
{
throw new NotImplementedException();
throw new NotSupportedException();
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulusByThis(Complex dividend, Matrix<Complex> result)
{
throw new NotSupportedException();
}
/// <summary>

49
src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/BiCgStab.cs

@ -39,6 +39,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#endif
/// <summary>
@ -76,24 +77,24 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator.
/// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
private IPreConditioner _preconditioner;
IPreConditioner _preconditioner;
/// <summary>
/// The iterative process controller.
/// </summary>
private IIterator _iterator;
IIterator _iterator;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
@ -101,7 +102,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public BiCgStab() : this(null, null)
public BiCgStab()
: this(null, null)
{
}
@ -124,7 +126,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IIterator iterator) : this(null, iterator)
public BiCgStab(IIterator iterator)
: this(null, iterator)
{
}
@ -136,7 +139,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param>
public BiCgStab(IPreConditioner preconditioner) : this(preconditioner, null)
public BiCgStab(IPreConditioner preconditioner)
: this(preconditioner, null)
{
}
@ -186,10 +190,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// </summary>
public ICalculationStatus IterationResult
{
get
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
}
/// <summary>
@ -278,9 +279,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
{
_preconditioner = new UnitPreconditioner();
}
_preconditioner.Initialize(matrix);
// Compute r_0 = b - Ax_0 for some initial guess x_0
// In this case we take x_0 = vector
// This is basically a SAXPY so it could be made a lot faster
@ -312,7 +313,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
{
// rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
var oldRho = currentRho;
currentRho = tempResiduals.DotProduct(residuals);
currentRho = tempResiduals.ConjugateDotProduct(residuals);
// if (rho_(i-1) == 0) // METHOD FAILS
// If rho is only 1 ULP from zero then we fail.
@ -325,7 +326,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
if (iterationNumber != 0)
{
// beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1))
var beta = (currentRho / oldRho) * (alpha / omega);
var beta = (currentRho/oldRho)*(alpha/omega);
// p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
nu.Multiply(-omega, temp);
@ -344,12 +345,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// SOLVE Mp~ = p_i // M = preconditioner
_preconditioner.Approximate(vecP, vecPdash);
// nu_i = Ap~
matrix.Multiply(vecPdash, nu);
// alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i)
alpha = currentRho * 1 / tempResiduals.DotProduct(nu);
alpha = currentRho*1/tempResiduals.ConjugateDotProduct(nu);
// s = r_(i-1) - alpha_i nu_i
nu.Multiply(-alpha, temp);
@ -393,7 +394,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(vecSdash, temp);
// omega_i = temp^T s / temp^T temp
omega = temp.DotProduct(vecS) / temp.DotProduct(temp);
omega = temp.ConjugateDotProduct(vecS)/temp.ConjugateDotProduct(temp);
// x_i = x_(i-1) + alpha_i p^ + omega_i s^
temp.Multiply(-omega, residuals);
@ -437,11 +438,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="residual">Residual values in <see cref="Vector"/>.</param>
/// <param name="x">Instance of the <see cref="Vector"/> x.</param>
/// <param name="b">Instance of the <see cref="Vector"/> b.</param>
private static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
{
// -Ax = residual
matrix.Multiply(x, residual);
// Do not use residual = residual.Negate() because it creates another object
residual.Multiply(-1, residual);
@ -457,7 +458,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
{
if (_hasBeenStopped)
{
@ -493,7 +494,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
throw new ArgumentNullException("input");
}
var result = (Matrix)matrix.CreateMatrix(input.RowCount, input.ColumnCount);
var result = (Matrix) matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result);
return result;
}
@ -529,7 +530,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, (Vector)input.Column(column));
var solution = Solve(matrix, (Vector) input.Column(column));
foreach (var element in solution.GetIndexedEnumerator())
{
result.At(element.Item1, column, element.Item2);

15
src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/GpBiCg.cs

@ -39,6 +39,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#endif
/// <summary>
@ -377,7 +378,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(temp, s);
// alpha_k = (r*_0 * r_k) / (r*_0 * s_k)
var alpha = rdash.DotProduct(residuals)/rdash.DotProduct(s);
var alpha = rdash.ConjugateDotProduct(residuals)/rdash.ConjugateDotProduct(s);
// y_k = t_(k-1) - r_k - alpha_k * w_(k-1) + alpha_k s_k
s.Subtract(w, temp);
@ -399,7 +400,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// c_k = A d_k
matrix.Multiply(temp, c);
var cdot = c.DotProduct(c);
var cdot = c.ConjugateDotProduct(c);
// cDot can only be zero if c is a zero vector
// We'll set cDot to 1 if it is zero to prevent NaN's
@ -414,7 +415,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// to do at least one at the start to initialize the
// system, but we'll only have to take special measures
// if we don't do any so ...
var ctdot = c.DotProduct(t);
var ctdot = c.ConjugateDotProduct(t);
Complex eta;
Complex sigma;
if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber))
@ -427,7 +428,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
}
else
{
var ydot = y.DotProduct(y);
var ydot = y.ConjugateDotProduct(y);
// yDot can only be zero if y is a zero vector
// We'll set yDot to 1 if it is zero to prevent NaN's
@ -438,8 +439,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
ydot = 1.0;
}
var ytdot = y.DotProduct(t);
var cydot = c.DotProduct(y);
var ytdot = y.ConjugateDotProduct(t);
var cydot = c.ConjugateDotProduct(y);
var denom = (cdot*ydot) - (cydot*cydot);
@ -493,7 +494,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// beta_k = alpha_k / sigma_k * (r*_0 * r_(k+1)) / (r*_0 * r_k)
// But first we check if there is a possible NaN. If so just reset beta to zero.
beta = (!sigma.Real.AlmostEqual(0, 1) || !sigma.Imaginary.AlmostEqual(0, 1)) ? alpha/sigma*rdash.DotProduct(residuals)/rdash.DotProduct(t0) : 0;
beta = (!sigma.Real.AlmostEqual(0, 1) || !sigma.Imaginary.AlmostEqual(0, 1)) ? alpha/sigma*rdash.ConjugateDotProduct(residuals)/rdash.ConjugateDotProduct(t0) : 0;
// w_k = c_k + beta_k s_k
s.Multiply(beta, temp2);

89
src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/MlkBiCgStab.cs

@ -43,6 +43,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#endif
/// <summary>
@ -73,39 +74,39 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <summary>
/// The default number of starting vectors.
/// </summary>
private const int DefaultNumberOfStartingVectors = 50;
const int DefaultNumberOfStartingVectors = 50;
/// <summary>
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator.
/// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
private IPreConditioner _preconditioner;
IPreConditioner _preconditioner;
/// <summary>
/// The iterative process controller.
/// </summary>
private IIterator _iterator;
IIterator _iterator;
/// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary>
private IList<Vector> _startingVectors;
IList<Vector> _startingVectors;
/// <summary>
/// The number of starting vectors used by the algorithm
/// </summary>
private int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
@ -114,7 +115,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public MlkBiCgStab() : this(null, null)
public MlkBiCgStab()
: this(null, null)
{
}
@ -137,7 +139,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IIterator iterator) : this(null, iterator)
public MlkBiCgStab(IIterator iterator)
: this(null, iterator)
{
}
@ -149,7 +152,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param>
public MlkBiCgStab(IPreConditioner preconditioner) : this(preconditioner, null)
public MlkBiCgStab(IPreConditioner preconditioner)
: this(preconditioner, null)
{
}
@ -186,10 +190,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
public int NumberOfStartingVectors
{
[DebuggerStepThrough]
get
{
return _numberOfStartingVectors;
}
get { return _numberOfStartingVectors; }
[DebuggerStepThrough]
set
@ -236,10 +237,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
public IList<Vector> StartingVectors
{
[DebuggerStepThrough]
get
{
return _startingVectors;
}
get { return _startingVectors; }
[DebuggerStepThrough]
set
@ -261,10 +259,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
public ICalculationStatus IterationResult
{
[DebuggerStepThrough]
get
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
}
/// <summary>
@ -348,7 +343,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
{
_preconditioner = new UnitPreconditioner();
}
_preconditioner.Initialize(matrix);
// Choose an initial guess x_0
@ -402,7 +397,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
Vector zw = new DenseVector(residuals.Count);
var d = CreateVectorArray(_startingVectors.Count, residuals.Count);
// g_0 = r_0
var g = CreateVectorArray(_startingVectors.Count, residuals.Count);
residuals.CopyTo(g[k - 1]);
@ -420,14 +415,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(gtemp, w[k - 1]);
// c_((j-1)k+k) = q^T_1 w_((j-1)k+k)
c[k - 1] = _startingVectors[0].DotProduct(w[k - 1]);
c[k - 1] = _startingVectors[0].ConjugateDotProduct(w[k - 1]);
if (c[k - 1].Real.AlmostEqual(0, 1) && c[k - 1].Imaginary.AlmostEqual(0, 1))
{
throw new Exception("Iterative solver experience a numerical break down");
}
// alpha_(jk+1) = q^T_1 r_((j-1)k+k) / c_((j-1)k+k)
var alpha = _startingVectors[0].DotProduct(residuals) / c[k - 1];
var alpha = _startingVectors[0].ConjugateDotProduct(residuals)/c[k - 1];
// u_(jk+1) = r_((j-1)k+k) - alpha_(jk+1) w_((j-1)k+k)
w[k - 1].Multiply(-alpha, temp);
@ -439,7 +434,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2
matrix.Multiply(temp1, temp);
var rho = temp.DotProduct(temp);
var rho = temp.ConjugateDotProduct(temp);
// If rho is zero then temp is a zero vector and we're probably
// about to have zero residuals (i.e. an exact solution).
@ -449,7 +444,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
rho = 1.0;
}
rho = -u.DotProduct(temp) / rho;
rho = -u.ConjugateDotProduct(temp)/rho;
// r_(jk+1) = rho_(j+1) A u~_(jk+1) + u_(jk+1)
u.CopyTo(residuals);
@ -502,7 +497,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
for (var s = i; s < k - 1; s++)
{
// beta^(jk+i)_((j-1)k+s) = -q^t_(s+1) z_d / c_((j-1)k+s)
beta = -_startingVectors[s + 1].DotProduct(zd) / c[s];
beta = -_startingVectors[s + 1].ConjugateDotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_((j-1)k+s) d_((j-1)k+s)
d[s].Multiply(beta, temp);
@ -521,7 +516,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
}
}
beta = rho * c[k - 1];
beta = rho*c[k - 1];
if (beta.Real.AlmostEqual(0, 1) && beta.Imaginary.AlmostEqual(0, 1))
{
throw new Exception("Iterative solver experience a numerical break down");
@ -530,7 +525,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// beta^(jk+i)_((j-1)k+k) = -(q^T_1 (r_(jk+1) + rho_(j+1) z_w)) / (rho_(j+1) c_((j-1)k+k))
zw.Multiply(rho, temp2);
residuals.Add(temp2, temp);
beta = -_startingVectors[0].DotProduct(temp) / beta;
beta = -_startingVectors[0].ConjugateDotProduct(temp)/beta;
// z_g = z_g + beta^(jk+i)_((j-1)k+k) g_((j-1)k+k)
g[k - 1].Multiply(beta, temp);
@ -550,7 +545,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
for (var s = 0; s < i - 1; s++)
{
// beta^(jk+i)_(jk+s) = -q^T_s+1 z_d / c_(jk+s)
beta = -_startingVectors[s + 1].DotProduct(zd) / c[s];
beta = -_startingVectors[s + 1].ConjugateDotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_(jk+s) * d_(jk+s)
d[s].Multiply(beta, temp);
@ -573,14 +568,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
if (i < k - 1)
{
// c_(jk+1) = q^T_i+1 d_(jk+i)
c[i] = _startingVectors[i + 1].DotProduct(d[i]);
c[i] = _startingVectors[i + 1].ConjugateDotProduct(d[i]);
if (c[i].Real.AlmostEqual(0, 1) && c[i].Imaginary.AlmostEqual(0, 1))
{
throw new Exception("Iterative solver experience a numerical break down");
}
// alpha_(jk+i+1) = q^T_(i+1) u_(jk+i) / c_(jk+i)
alpha = _startingVectors[i + 1].DotProduct(u) / c[i];
alpha = _startingVectors[i + 1].ConjugateDotProduct(u)/c[i];
// u_(jk+i+1) = u_(jk+i) - alpha_(jk+i+1) d_(jk+i)
d[i].Multiply(-alpha, temp);
@ -591,7 +586,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
_preconditioner.Approximate(g[i], gtemp);
// x_(jk+i+1) = x_(jk+i) + rho_(j+1) alpha_(jk+i+1) g~_(jk+i)
gtemp.Multiply(rho * alpha, temp);
gtemp.Multiply(rho*alpha, temp);
xtemp.Add(temp, temp2);
temp2.CopyTo(xtemp);
@ -599,7 +594,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(gtemp, w[i]);
// r_(jk+i+1) = r_(jk+i) - rho_(j+1) alpha_(jk+i+1) w_(jk+i)
w[i].Multiply(-rho * alpha, temp);
w[i].Multiply(-rho*alpha, temp);
residuals.Add(temp, temp2);
temp2.CopyTo(residuals);
@ -626,7 +621,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="maximumNumberOfStartingVectors">Maximum number</param>
/// <param name="numberOfVariables">Number of variables</param>
/// <returns>Number of starting vectors to create</returns>
private static int NumberOfStartingVectorsToCreate(int maximumNumberOfStartingVectors, int numberOfVariables)
static int NumberOfStartingVectorsToCreate(int maximumNumberOfStartingVectors, int numberOfVariables)
{
// Create no more starting vectors than the size of the problem - 1
return Math.Min(maximumNumberOfStartingVectors, (numberOfVariables - 1));
@ -643,7 +638,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// the <paramref name="numberOfVariables"/> is smaller than
/// the <paramref name="maximumNumberOfStartingVectors"/>.
/// </returns>
private static IList<Vector> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables)
static IList<Vector> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables)
{
// Create no more starting vectors than the size of the problem - 1
// Get random values and then orthogonalize them with
@ -677,10 +672,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
var result = new List<Vector>();
for (var i = 0; i < orthogonalMatrix.ColumnCount; i++)
{
result.Add((Vector)orthogonalMatrix.Column(i));
result.Add((Vector) orthogonalMatrix.Column(i));
// Normalize the result vector
result[i].Multiply(1 / result[i].Norm(2), result[i]);
result[i].Multiply(1/result[i].L2Norm(), result[i]);
}
return result;
@ -692,7 +687,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="arraySize">Number of vectors</param>
/// <param name="vectorSize">Size of each vector</param>
/// <returns>Array of random vectors</returns>
private static Vector[] CreateVectorArray(int arraySize, int vectorSize)
static Vector[] CreateVectorArray(int arraySize, int vectorSize)
{
var result = new Vector[arraySize];
for (var i = 0; i < result.Length; i++)
@ -710,7 +705,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="residual">Residual <see cref="Vector"/> data.</param>
/// <param name="x">x <see cref="Vector"/> data.</param>
/// <param name="b">b <see cref="Vector"/> data.</param>
private static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
{
// -Ax = residual
matrix.Multiply(x, residual);
@ -728,7 +723,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
{
if (_hasBeenStopped)
{
@ -764,7 +759,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
throw new ArgumentNullException("input");
}
var result = (Matrix)matrix.CreateMatrix(input.RowCount, input.ColumnCount);
var result = (Matrix) matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result);
return result;
}
@ -800,7 +795,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, (Vector)input.Column(column));
var solution = Solve(matrix, (Vector) input.Column(column));
foreach (var element in solution.GetIndexedEnumerator())
{
result.At(element.Item1, column, element.Item2);

13
src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/TFQMR.cs

@ -39,6 +39,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex;
#else
using Complex = System.Numerics.Complex;
#endif
/// <summary>
@ -282,15 +283,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
var temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.Norm(2);
// Define the scalars
Complex alpha = 0;
Complex eta = 0;
double theta = 0;
var tau = startNorm.Real;
// Initialize
var tau = input.L2Norm().Real;
Complex rho = tau*tau;
// Calculate the initial values for v
@ -311,7 +310,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
if (IsEven(iterationNumber))
{
// sigma = (v, r)
var sigma = v.DotProduct(r.Conjugate());
var sigma = r.ConjugateDotProduct(v);
if (sigma.Real.AlmostEqual(0, 1) && sigma.Imaginary.AlmostEqual(0, 1))
{
// FAIL HERE
@ -349,7 +348,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
yinternal.Add(temp, d);
// theta = ||pseudoResiduals||_2 / tau
theta = pseudoResiduals.Norm(2).Real/tau;
theta = pseudoResiduals.L2Norm().Real/tau;
var c = 1/Math.Sqrt(1 + (theta*theta));
// tau = tau * theta * c
@ -392,7 +391,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
break;
}
var rhoNew = pseudoResiduals.DotProduct(r.Conjugate());
var rhoNew = r.ConjugateDotProduct(pseudoResiduals);
var beta = rhoNew/rho;
// Update rho for the next loop

2
src/Numerics/LinearAlgebra/Complex/Solvers/Preconditioners/Ilutp.cs

@ -394,7 +394,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Preconditioners
// pivot the row
PivotRow(workVector);
var vectorNorm = workVector.Norm(Double.PositiveInfinity);
var vectorNorm = workVector.InfinityNorm();
// for j = 1, .. , i - 1)
for (var j = 0; j < i; j++)

2
src/Numerics/LinearAlgebra/Complex/Solvers/StopCriterium/DivergenceStopCriterium.cs

@ -250,7 +250,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.StopCriterium
// Store the infinity norms of both the solution and residual vectors
// These values will be used to calculate the relative drop in residuals later on.
_residualHistory[_residualHistory.Length - 1] = residualVector.Norm(Double.PositiveInfinity).Real;
_residualHistory[_residualHistory.Length - 1] = residualVector.InfinityNorm().Real;
// Check if we have NaN's. If so we've gone way beyond normal divergence.
// Stop the iteration.

4
src/Numerics/LinearAlgebra/Complex/Solvers/StopCriterium/FailureStopCriterium.cs

@ -105,8 +105,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.StopCriterium
}
// Store the infinity norms of both the solution and residual vectors
var residualNorm = residualVector.Norm(Double.PositiveInfinity);
var solutionNorm = solutionVector.Norm(Double.PositiveInfinity);
var residualNorm = residualVector.InfinityNorm();
var solutionNorm = solutionVector.InfinityNorm();
if (Double.IsNaN(solutionNorm.Real) || Double.IsNaN(residualNorm.Real))
{

4
src/Numerics/LinearAlgebra/Complex/Solvers/StopCriterium/ResidualStopCriterium.cs

@ -257,11 +257,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.StopCriterium
// Store the infinity norms of both the solution and residual vectors
// These values will be used to calculate the relative drop in residuals
// later on.
var residualNorm = residualVector.Norm(Double.PositiveInfinity);
var residualNorm = residualVector.InfinityNorm();
// Check the residuals by calculating:
// ||r_i|| <= stop_tol * ||b||
var stopCriterium = ComputeStopCriterium(sourceVector.Norm(Double.PositiveInfinity).Real);
var stopCriterium = ComputeStopCriterium(sourceVector.InfinityNorm().Real);
// First check that we have real numbers not NaN's.
// NaN's can occur when the iterative process diverges so we

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

@ -1052,9 +1052,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<Complex> other, Matrix<Complex> result)
protected override void DoPointwiseDivide(Matrix<Complex> divisor, Matrix<Complex> result)
{
result.Clear();
@ -1073,7 +1073,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
if (!values[j].IsZero())
{
result.At(i, columnIndices[j], values[j]/other.At(i, columnIndices[j]));
result.At(i, columnIndices[j], values[j]/divisor.At(i, columnIndices[j]));
}
}
}

120
src/Numerics/LinearAlgebra/Complex/SparseVector.cs

@ -540,16 +540,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Computes the dot product between this vector and another vector.
/// </summary>
/// <param name="other">
/// The other vector to add.
/// </param>
/// <returns>s
/// The result of the addition.
/// </returns>
/// <param name="other">The other vector.</param>
/// <returns>The sum of a[i]*b[i] for all i.</returns>
protected override Complex DoDotProduct(Vector<Complex> other)
{
var result = Complex.Zero;
if (ReferenceEquals(this, other))
{
for (var i = 0; i < _storage.ValueCount; i++)
@ -564,7 +559,31 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
result += _storage.Values[i] * other.At(_storage.Indices[i]);
}
}
return result;
}
/// <summary>
/// Computes the dot product between the conjugate of this vector and another vector.
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>The sum of conj(a[i])*b[i] for all i.</returns>
protected override Complex DoConjugateDotProduct(Vector<Complex> other)
{
var result = Complex.Zero;
if (ReferenceEquals(this, other))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _storage.Values[i].Conjugate() * _storage.Values[i];
}
}
else
{
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _storage.Values[i].Conjugate() * other.At(_storage.Indices[i]);
}
}
return result;
}
@ -744,25 +763,58 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
result += _storage.Values[i];
}
return result;
}
/// <summary>
/// Computes the sum of the absolute value of the vector's elements.
/// Calculates the L1 norm of the vector, also known as Manhattan norm.
/// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns>
public override Complex SumMagnitudes()
/// <returns>The sum of the absolute values.</returns>
public override Complex L1Norm()
{
double result = 0;
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _storage.Values[i].Magnitude;
}
return result;
}
/// <summary>
/// Calculates the infinity norm of the vector.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override Complex InfinityNorm()
{
return CommonParallel.Aggregate(0, _storage.ValueCount, i => _storage.Values[i].Magnitude, Math.Max, 0d);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override Complex Norm(double p)
{
if (p < 0d) throw new ArgumentOutOfRangeException("p");
if (_storage.ValueCount == 0)
{
return Complex.Zero;
}
if (p == 1d) return L1Norm();
if (p == 2d) return L2Norm();
if (Double.IsPositiveInfinity(p)) return InfinityNorm();
var sum = 0d;
for (var index = 0; index < _storage.ValueCount; index++)
{
sum += Math.Pow(_storage.Values[index].Magnitude, p);
}
return Math.Pow(sum, 1.0 / p);
}
/// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary>
@ -790,11 +842,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise multiply with this one.</param>
/// <param name="divisor">The vector to pointwise multiply with this one.</param>
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseDivide(Vector<Complex> other, Vector<Complex> result)
protected override void DoPointwiseDivide(Vector<Complex> divisor, Vector<Complex> result)
{
if (ReferenceEquals(this, other))
if (ReferenceEquals(this, divisor))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
@ -806,7 +858,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _storage.Indices[i];
result.At(index, _storage.Values[i] / other.At(index));
result.At(index, _storage.Values[i] / divisor.At(index));
}
}
}
@ -858,42 +910,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return OuterProduct(this, v);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override Complex Norm(double p)
{
if (1 > p)
{
throw new ArgumentOutOfRangeException("p");
}
if (_storage.ValueCount == 0)
{
return 0.0;
}
if (2.0 == p)
{
return _storage.Values.Aggregate(Complex.Zero, SpecialFunctions.Hypotenuse).Magnitude;
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(0, _storage.ValueCount, i => _storage.Values[i].Magnitude, Math.Max, 0d);
}
var sum = 0.0;
for (var index = 0; index < _storage.ValueCount; index++)
{
sum += Math.Pow(_storage.Values[index].Magnitude, p);
}
return Math.Pow(sum, 1.0 / p);
}
#region Parse Functions
/// <summary>

95
src/Numerics/LinearAlgebra/Complex/Vector.cs

@ -140,27 +140,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Divides each element of the vector by a scalar and stores the result in the result vector.
/// </summary>
/// <param name="scalar">
/// <param name="divisor">
/// The scalar to divide with.
/// </param>
/// <param name="result">
/// The vector to store the result of the division.
/// </param>
protected override void DoDivide(Complex scalar, Vector<Complex> result)
protected override void DoDivide(Complex divisor, Vector<Complex> result)
{
DoMultiply(1 / scalar, result);
DoMultiply(1 / divisor, result);
}
/// <summary>
/// Divides a scalar by each element of the vector and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to divide.</param>
/// <param name="dividend">The scalar to divide.</param>
/// <param name="result">The vector to store the result of the division.</param>
protected override void DoDivideByThis(Complex scalar, Vector<Complex> result)
protected override void DoDivideByThis(Complex dividend, Vector<Complex> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, scalar / At(index));
result.At(index, dividend / At(index));
}
}
@ -180,22 +180,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise divide this one by.</param>
/// <param name="divisor">The vector to pointwise divide this one by.</param>
/// <param name="result">The vector to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Vector<Complex> other, Vector<Complex> result)
protected override void DoPointwiseDivide(Vector<Complex> divisor, Vector<Complex> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) / other.At(index));
result.At(index, At(index) / divisor.At(index));
}
}
/// <summary>
/// Pointwise modulus this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise modulus this one by.</param>
/// <param name="divisor">The vector to pointwise modulus this one by.</param>
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Vector<Complex> other, Vector<Complex> result)
protected override void DoPointwiseModulus(Vector<Complex> divisor, Vector<Complex> result)
{
throw new NotSupportedException();
}
@ -203,28 +203,37 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Computes the dot product between this vector and another vector.
/// </summary>
/// <param name="other">
/// The other vector to add.
/// </param>
/// <returns>
/// The result of the addition.
/// </returns>
/// <param name="other">The other vector.</param>
/// <returns>The sum of a[i]*b[i] for all i.</returns>
protected override Complex DoDotProduct(Vector<Complex> other)
{
var dot = Complex.Zero;
for (var i = 0; i < Count; i++)
{
dot += At(i) * other.At(i);
}
return dot;
}
/// <summary>
/// Computes the dot product between the conjugate of this vector and another vector.
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>The sum of conj(a[i])*b[i] for all i.</returns>
protected override Complex DoConjugateDotProduct(Vector<Complex> other)
{
var dot = Complex.Zero;
for (var i = 0; i < Count; i++)
{
dot += At(i).Conjugate() * other.At(i);
}
return dot;
}
/// <summary>
/// Computes the modulus for each element of the vector for the given divisor.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulus(Complex divisor, Vector<Complex> result)
{
@ -234,9 +243,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary>
/// Computes the modulus for the given dividend for each element of the vector.
/// </summary>
/// <param name="scalar">The dividend to use.</param>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulusByThis(Complex scalar, Vector<Complex> result)
protected override void DoModulusByThis(Complex dividend, Vector<Complex> result)
{
throw new NotSupportedException();
}
@ -308,31 +317,45 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override Complex Sum()
{
var sum = Complex.Zero;
for (var i = 0; i < Count; i++)
{
sum += At(i);
}
return sum;
}
/// <summary>
/// Computes the sum of the absolute value of the vector's elements.
/// Calculates the L1 norm of the vector, also known as Manhattan norm.
/// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns>
public override Complex SumMagnitudes()
/// <returns>The sum of the absolute values.</returns>
public override Complex L1Norm()
{
var sum = Complex.Zero;
for (var i = 0; i < Count; i++)
{
sum += At(i).Magnitude;
}
return sum;
}
/// <summary>
/// Calculates the L2 norm of the vector, also known as Euclidean norm.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override Complex L2Norm()
{
return DoConjugateDotProduct(this).SquareRoot();
}
/// <summary>
/// Calculates the infinity norm of the vector.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override Complex InfinityNorm()
{
return CommonParallel.Aggregate(0, Count, i => At(i).Magnitude, Math.Max, 0d);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
@ -344,23 +367,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// </returns>
public override Complex Norm(double p)
{
if (p < 0.0)
{
throw new ArgumentOutOfRangeException("p");
}
if (p < 0d) throw new ArgumentOutOfRangeException("p");
if (double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(0, Count, i => At(i).Magnitude, Math.Max, 0d);
}
var sum = 0.0;
if (p == 1d) return L1Norm();
if (p == 2d) return L2Norm();
if (Double.IsPositiveInfinity(p)) return InfinityNorm();
var sum = 0d;
for (var index = 0; index < Count; index++)
{
sum += Math.Pow(At(index).Magnitude, p);
}
return Math.Pow(sum, 1.0 / p);
}

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

@ -28,6 +28,8 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.Threading;
namespace MathNet.Numerics.LinearAlgebra.Complex32
{
using Algorithms.LinearAlgebra;
@ -583,6 +585,24 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
}
/// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary>
/// <param name="divisor">The scalar to divide the matrix with.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(Complex32 divisor, Matrix<Complex32> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoDivide(divisor, result);
}
else
{
Control.LinearAlgebraProvider.ScaleArray(1.0f/divisor, _values, denseResult._values);
}
}
/// <summary>
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
/// </summary>
@ -606,16 +626,16 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<Complex32> other, Matrix<Complex32> result)
protected override void DoPointwiseDivide(Matrix<Complex32> divisor, Matrix<Complex32> result)
{
var denseOther = other as DenseMatrix;
var denseOther = divisor as DenseMatrix;
var denseResult = result as DenseMatrix;
if (denseOther == null || denseResult == null)
{
base.DoPointwiseDivide(other, result);
base.DoPointwiseDivide(divisor, result);
}
else
{
@ -623,6 +643,30 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
}
/// <summary>
/// Add a scalar to each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(Complex32 scalar, Matrix<Complex32> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoAdd(scalar, result);
return;
}
CommonParallel.For(0, _values.Length, 4096, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] = _values[i] + scalar;
}
});
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>
@ -644,6 +688,30 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
}
/// <summary>
/// Subtracts a scalar from each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to subtract.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(Complex32 scalar, Matrix<Complex32> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoSubtract(scalar, result);
return;
}
CommonParallel.For(0, _values.Length, 4096, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] = _values[i] - scalar;
}
});
}
/// <summary>
/// Subtracts another matrix from this matrix.
/// </summary>

122
src/Numerics/LinearAlgebra/Complex32/DenseVector.cs

@ -429,14 +429,33 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Computes the dot product between this vector and another vector.
/// </summary>
/// <param name="other">The other vector to add.</param>
/// <returns>s
/// The result of the addition.</returns>
/// <param name="other">The other vector.</param>
/// <returns>The sum of a[i]*b[i] for all i.</returns>
protected override Complex32 DoDotProduct(Vector<Complex32> other)
{
var denseVector = other as DenseVector;
return denseVector == null
? base.DoDotProduct(other)
: Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
}
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
/// <summary>
/// Computes the dot product between the conjugate of this vector and another vector.
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>The sum of conj(a[i])*b[i] for all i.</returns>
protected override Complex32 DoConjugateDotProduct(Vector<Complex32> other)
{
var denseVector = other as DenseVector;
if (denseVector == null) return base.DoConjugateDotProduct(other);
// TODO: provide native cdotc routine
var dot = Complex32.Zero;
for (var i = 0; i < _values.Length; i++)
{
dot += _values[i].Conjugate() * denseVector._values[i];
}
return dot;
}
/// <summary>
@ -575,31 +594,67 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override Complex32 Sum()
{
var sum = Complex32.Zero;
for (var i = 0; i < _length; i++)
{
sum += _values[i];
}
return sum;
}
/// <summary>
/// Computes the sum of the absolute value of the vector's elements.
/// Calculates the L1 norm of the vector, also known as Manhattan norm.
/// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns>
public override Complex32 SumMagnitudes()
/// <returns>The sum of the absolute values.</returns>
public override Complex32 L1Norm()
{
var sum = Complex32.Zero;
for (var i = 0; i < _length; i++)
{
sum += _values[i].Magnitude;
}
return sum;
}
/// <summary>
/// Calculates the L2 norm of the vector, also known as Euclidean norm.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override Complex32 L2Norm()
{
// TODO: native provider
return _values.Aggregate(Complex32.Zero, SpecialFunctions.Hypotenuse).Magnitude;
}
/// <summary>
/// Calculates the infinity norm of the vector.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override Complex32 InfinityNorm()
{
return CommonParallel.Aggregate(_values, (i, v) => v.Magnitude, Math.Max, 0f);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override Complex32 Norm(double p)
{
if (p < 0d) throw new ArgumentOutOfRangeException("p");
if (p == 1d) return L1Norm();
if (p == 2d) return L2Norm();
if (Double.IsPositiveInfinity(p)) return InfinityNorm();
var sum = 0d;
for (var i = 0; i < _length; i++)
{
sum += Math.Pow(_values[i].Magnitude, p);
}
return (float)Math.Pow(sum, 1.0 / p);
}
/// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary>
@ -623,17 +678,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise divide this one by.</param>
/// <param name="divisor">The vector to pointwise divide this one by.</param>
/// <param name="result">The vector to store the result of the pointwise division.</param>
/// <remarks></remarks>
protected override void DoPointwiseDivide(Vector<Complex32> other, Vector<Complex32> result)
protected override void DoPointwiseDivide(Vector<Complex32> divisor, Vector<Complex32> result)
{
var denseOther = other as DenseVector;
var denseOther = divisor as DenseVector;
var denseResult = result as DenseVector;
if (denseOther == null || denseResult == null)
{
base.DoPointwiseDivide(other, result);
base.DoPointwiseDivide(divisor, result);
}
else
{
@ -688,43 +743,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return OuterProduct(this, v);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override Complex32 Norm(double p)
{
if (p < 0.0)
{
throw new ArgumentOutOfRangeException("p");
}
if (1.0 == p)
{
return SumMagnitudes();
}
if (2.0 == p)
{
return _values.Aggregate(Complex32.Zero, SpecialFunctions.Hypotenuse).Magnitude;
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(_values, (i, v) => v.Magnitude, Math.Max, 0f);
}
var sum = 0.0;
for (var i = 0; i < _length; i++)
{
sum += Math.Pow(_values[i].Magnitude, p);
}
return (float)Math.Pow(sum, 1.0 / p);
}
#region Parse Functions
/// <summary>

2
src/Numerics/LinearAlgebra/Complex32/Factorization/UserGramSchmidt.cs

@ -69,7 +69,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
for (var k = 0; k < MatrixQ.ColumnCount; k++)
{
var norm = MatrixQ.Column(k).Norm(2).Real;
var norm = MatrixQ.Column(k).L2Norm().Real;
if (norm == 0.0f)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);

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

@ -124,6 +124,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return norm;
}
/// <summary>
/// Add a scalar to each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(Complex32 scalar, Matrix<Complex32> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + scalar);
}
}
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>
@ -142,6 +158,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
}
/// <summary>
/// Subtracts a scalar from each element of the vector and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to subtract.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(Complex32 scalar, Matrix<Complex32> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - scalar);
}
}
}
/// <summary>
/// Subtracts another matrix from this matrix.
/// </summary>
@ -198,11 +230,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary>
/// <param name="scalar">The scalar to divide the matrix with.</param>
/// <param name="divisor">The scalar to divide the matrix with.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(Complex32 scalar, Matrix<Complex32> result)
protected override void DoDivide(Complex32 divisor, Matrix<Complex32> result)
{
DoMultiply(1.0f / scalar, result);
DoMultiply(1.0f / divisor, result);
}
/// <summary>
/// Divides a scalar by each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="dividend">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivideByThis(Complex32 dividend, Matrix<Complex32> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, dividend / At(i, j));
}
}
}
/// <summary>
@ -339,27 +387,47 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<Complex32> other, Matrix<Complex32> result)
protected override void DoPointwiseDivide(Matrix<Complex32> divisor, Matrix<Complex32> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j) / other.At(i, j));
result.At(i, j, At(i, j) / divisor.At(i, j));
}
}
}
/// <summary>
/// Pointwise modulus this matrix with another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="divisor">The pointwise denominator matrix to use</param>
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Matrix<Complex32> divisor, Matrix<Complex32> result)
{
throw new NotSupportedException();
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(Complex32 divisor, Matrix<Complex32> result)
{
throw new NotImplementedException();
throw new NotSupportedException();
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulusByThis(Complex32 dividend, Matrix<Complex32> result)
{
throw new NotSupportedException();
}
/// <summary>

48
src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/BiCgStab.cs

@ -71,24 +71,24 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator.
/// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
private IPreConditioner _preconditioner;
IPreConditioner _preconditioner;
/// <summary>
/// The iterative process controller.
/// </summary>
private IIterator _iterator;
IIterator _iterator;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class.
/// </summary>
@ -96,7 +96,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public BiCgStab() : this(null, null)
public BiCgStab()
: this(null, null)
{
}
@ -119,7 +120,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process. </param>
public BiCgStab(IIterator iterator) : this(null, iterator)
public BiCgStab(IIterator iterator)
: this(null, iterator)
{
}
@ -131,7 +133,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param>
public BiCgStab(IPreConditioner preconditioner) : this(preconditioner, null)
public BiCgStab(IPreConditioner preconditioner)
: this(preconditioner, null)
{
}
@ -181,10 +184,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// </summary>
public ICalculationStatus IterationResult
{
get
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
}
/// <summary>
@ -273,9 +273,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
{
_preconditioner = new UnitPreconditioner();
}
_preconditioner.Initialize(matrix);
// Compute r_0 = b - Ax_0 for some initial guess x_0
// In this case we take x_0 = vector
// This is basically a SAXPY so it could be made a lot faster
@ -307,7 +307,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
{
// rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
var oldRho = currentRho;
currentRho = tempResiduals.DotProduct(residuals);
currentRho = tempResiduals.ConjugateDotProduct(residuals);
// if (rho_(i-1) == 0) // METHOD FAILS
// If rho is only 1 ULP from zero then we fail.
@ -320,7 +320,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
if (iterationNumber != 0)
{
// beta_(i-1) = (rho_(i-1)/rho_(i-2))(alpha_(i-1)/omega(i-1))
var beta = (currentRho / oldRho) * (alpha / omega);
var beta = (currentRho/oldRho)*(alpha/omega);
// p_i = r_(i-1) + beta_(i-1)(p_(i-1) - omega_(i-1) * nu_(i-1))
nu.Multiply(-omega, temp);
@ -339,12 +339,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// SOLVE Mp~ = p_i // M = preconditioner
_preconditioner.Approximate(vecP, vecPdash);
// nu_i = Ap~
matrix.Multiply(vecPdash, nu);
// alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i)
alpha = currentRho * 1 / tempResiduals.DotProduct(nu);
alpha = currentRho*1/tempResiduals.ConjugateDotProduct(nu);
// s = r_(i-1) - alpha_i nu_i
nu.Multiply(-alpha, temp);
@ -388,7 +388,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(vecSdash, temp);
// omega_i = temp^T s / temp^T temp
omega = temp.DotProduct(vecS) / temp.DotProduct(temp);
omega = temp.ConjugateDotProduct(vecS)/temp.ConjugateDotProduct(temp);
// x_i = x_(i-1) + alpha_i p^ + omega_i s^
temp.Multiply(-omega, residuals);
@ -432,11 +432,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="residual">Residual values in <see cref="Vector"/>.</param>
/// <param name="x">Instance of the <see cref="Vector"/> x.</param>
/// <param name="b">Instance of the <see cref="Vector"/> b.</param>
private static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
{
// -Ax = residual
matrix.Multiply(x, residual);
// Do not use residual = residual.Negate() because it creates another object
residual.Multiply(-1, residual);
@ -452,7 +452,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
{
if (_hasBeenStopped)
{
@ -488,7 +488,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
throw new ArgumentNullException("input");
}
var result = (Matrix)matrix.CreateMatrix(input.RowCount, input.ColumnCount);
var result = (Matrix) matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result);
return result;
}
@ -524,7 +524,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, (Vector)input.Column(column));
var solution = Solve(matrix, (Vector) input.Column(column));
foreach (var element in solution.GetIndexedEnumerator())
{
result.At(element.Item1, column, element.Item2);

14
src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/GpBiCg.cs

@ -377,7 +377,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(temp, s);
// alpha_k = (r*_0 * r_k) / (r*_0 * s_k)
var alpha = rdash.DotProduct(residuals)/rdash.DotProduct(s);
var alpha = rdash.ConjugateDotProduct(residuals)/rdash.ConjugateDotProduct(s);
// y_k = t_(k-1) - r_k - alpha_k * w_(k-1) + alpha_k s_k
s.Subtract(w, temp);
@ -399,7 +399,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// c_k = A d_k
matrix.Multiply(temp, c);
var cdot = c.DotProduct(c);
var cdot = c.ConjugateDotProduct(c);
// cDot can only be zero if c is a zero vector
// We'll set cDot to 1 if it is zero to prevent NaN's
@ -414,7 +414,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// to do at least one at the start to initialize the
// system, but we'll only have to take special measures
// if we don't do any so ...
var ctdot = c.DotProduct(t);
var ctdot = c.ConjugateDotProduct(t);
Complex32 eta;
Complex32 sigma;
if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber))
@ -427,7 +427,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
}
else
{
var ydot = y.DotProduct(y);
var ydot = y.ConjugateDotProduct(y);
// yDot can only be zero if y is a zero vector
// We'll set yDot to 1 if it is zero to prevent NaN's
@ -438,8 +438,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
ydot = 1.0f;
}
var ytdot = y.DotProduct(t);
var cydot = c.DotProduct(y);
var ytdot = y.ConjugateDotProduct(t);
var cydot = c.ConjugateDotProduct(y);
var denom = (cdot*ydot) - (cydot*cydot);
@ -493,7 +493,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// beta_k = alpha_k / sigma_k * (r*_0 * r_(k+1)) / (r*_0 * r_k)
// But first we check if there is a possible NaN. If so just reset beta to zero.
beta = (!sigma.Real.AlmostEqual(0, 1) || !sigma.Imaginary.AlmostEqual(0, 1)) ? alpha/sigma*rdash.DotProduct(residuals)/rdash.DotProduct(t0) : 0;
beta = (!sigma.Real.AlmostEqual(0, 1) || !sigma.Imaginary.AlmostEqual(0, 1)) ? alpha/sigma*rdash.ConjugateDotProduct(residuals)/rdash.ConjugateDotProduct(t0) : 0;
// w_k = c_k + beta_k s_k
s.Multiply(beta, temp2);

90
src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/MlkBiCgStab.cs

@ -68,39 +68,39 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <summary>
/// The default number of starting vectors.
/// </summary>
private const int DefaultNumberOfStartingVectors = 50;
const int DefaultNumberOfStartingVectors = 50;
/// <summary>
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator.
/// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used.
/// </summary>
private IPreConditioner _preconditioner;
IPreConditioner _preconditioner;
/// <summary>
/// The iterative process controller.
/// </summary>
private IIterator _iterator;
IIterator _iterator;
/// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary>
private IList<Vector> _startingVectors;
IList<Vector> _startingVectors;
/// <summary>
/// The number of starting vectors used by the algorithm
/// </summary>
private int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
/// <summary>
/// Indicates if the user has stopped the solver.
/// </summary>
private bool _hasBeenStopped;
bool _hasBeenStopped;
/// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class.
@ -109,7 +109,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner.
/// </remarks>
public MlkBiCgStab() : this(null, null)
public MlkBiCgStab()
: this(null, null)
{
}
@ -132,7 +133,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// </para>
/// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process.</param>
public MlkBiCgStab(IIterator iterator) : this(null, iterator)
public MlkBiCgStab(IIterator iterator)
: this(null, iterator)
{
}
@ -144,7 +146,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// the standard settings.
/// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param>
public MlkBiCgStab(IPreConditioner preconditioner) : this(preconditioner, null)
public MlkBiCgStab(IPreConditioner preconditioner)
: this(preconditioner, null)
{
}
@ -181,10 +184,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
public int NumberOfStartingVectors
{
[DebuggerStepThrough]
get
{
return _numberOfStartingVectors;
}
get { return _numberOfStartingVectors; }
[DebuggerStepThrough]
set
@ -231,10 +231,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
public IList<Vector> StartingVectors
{
[DebuggerStepThrough]
get
{
return _startingVectors;
}
get { return _startingVectors; }
[DebuggerStepThrough]
set
@ -256,10 +253,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
public ICalculationStatus IterationResult
{
[DebuggerStepThrough]
get
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
}
/// <summary>
@ -348,7 +342,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
{
_preconditioner = new UnitPreconditioner();
}
_preconditioner.Initialize(matrix);
// Choose an initial guess x_0
@ -402,7 +396,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
Vector zw = new DenseVector(residuals.Count);
var d = CreateVectorArray(_startingVectors.Count, residuals.Count);
// g_0 = r_0
var g = CreateVectorArray(_startingVectors.Count, residuals.Count);
residuals.CopyTo(g[k - 1]);
@ -420,14 +414,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(gtemp, w[k - 1]);
// c_((j-1)k+k) = q^T_1 w_((j-1)k+k)
c[k - 1] = _startingVectors[0].DotProduct(w[k - 1]);
c[k - 1] = _startingVectors[0].ConjugateDotProduct(w[k - 1]);
if (c[k - 1].Real.AlmostEqual(0, 1) && c[k - 1].Imaginary.AlmostEqual(0, 1))
{
throw new Exception("Iterative solver experience a numerical break down");
}
// alpha_(jk+1) = q^T_1 r_((j-1)k+k) / c_((j-1)k+k)
var alpha = _startingVectors[0].DotProduct(residuals) / c[k - 1];
var alpha = _startingVectors[0].ConjugateDotProduct(residuals)/c[k - 1];
// u_(jk+1) = r_((j-1)k+k) - alpha_(jk+1) w_((j-1)k+k)
w[k - 1].Multiply(-alpha, temp);
@ -439,7 +433,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2
matrix.Multiply(temp1, temp);
var rho = temp.DotProduct(temp);
var rho = temp.ConjugateDotProduct(temp);
// If rho is zero then temp is a zero vector and we're probably
// about to have zero residuals (i.e. an exact solution).
@ -449,7 +443,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
rho = 1.0f;
}
rho = -u.DotProduct(temp) / rho;
rho = -u.ConjugateDotProduct(temp)/rho;
// r_(jk+1) = rho_(j+1) A u~_(jk+1) + u_(jk+1)
u.CopyTo(residuals);
@ -502,7 +496,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
for (var s = i; s < k - 1; s++)
{
// beta^(jk+i)_((j-1)k+s) = -q^t_(s+1) z_d / c_((j-1)k+s)
beta = -_startingVectors[s + 1].DotProduct(zd) / c[s];
beta = -_startingVectors[s + 1].ConjugateDotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_((j-1)k+s) d_((j-1)k+s)
d[s].Multiply(beta, temp);
@ -521,7 +515,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
}
}
beta = rho * c[k - 1];
beta = rho*c[k - 1];
if (beta.Real.AlmostEqual(0, 1) && beta.Imaginary.AlmostEqual(0, 1))
{
throw new Exception("Iterative solver experience a numerical break down");
@ -530,7 +524,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// beta^(jk+i)_((j-1)k+k) = -(q^T_1 (r_(jk+1) + rho_(j+1) z_w)) / (rho_(j+1) c_((j-1)k+k))
zw.Multiply(rho, temp2);
residuals.Add(temp2, temp);
beta = -_startingVectors[0].DotProduct(temp) / beta;
beta = -_startingVectors[0].ConjugateDotProduct(temp)/beta;
// z_g = z_g + beta^(jk+i)_((j-1)k+k) g_((j-1)k+k)
g[k - 1].Multiply(beta, temp);
@ -550,7 +544,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
for (var s = 0; s < i - 1; s++)
{
// beta^(jk+i)_(jk+s) = -q^T_s+1 z_d / c_(jk+s)
beta = -_startingVectors[s + 1].DotProduct(zd) / c[s];
beta = -_startingVectors[s + 1].ConjugateDotProduct(zd)/c[s];
// z_d = z_d + beta^(jk+i)_(jk+s) * d_(jk+s)
d[s].Multiply(beta, temp);
@ -573,14 +567,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
if (i < k - 1)
{
// c_(jk+1) = q^T_i+1 d_(jk+i)
c[i] = _startingVectors[i + 1].DotProduct(d[i]);
c[i] = _startingVectors[i + 1].ConjugateDotProduct(d[i]);
if (c[i].Real.AlmostEqual(0, 1) && c[i].Imaginary.AlmostEqual(0, 1))
{
throw new Exception("Iterative solver experience a numerical break down");
}
// alpha_(jk+i+1) = q^T_(i+1) u_(jk+i) / c_(jk+i)
alpha = _startingVectors[i + 1].DotProduct(u) / c[i];
alpha = _startingVectors[i + 1].ConjugateDotProduct(u)/c[i];
// u_(jk+i+1) = u_(jk+i) - alpha_(jk+i+1) d_(jk+i)
d[i].Multiply(-alpha, temp);
@ -591,7 +585,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
_preconditioner.Approximate(g[i], gtemp);
// x_(jk+i+1) = x_(jk+i) + rho_(j+1) alpha_(jk+i+1) g~_(jk+i)
gtemp.Multiply(rho * alpha, temp);
gtemp.Multiply(rho*alpha, temp);
xtemp.Add(temp, temp2);
temp2.CopyTo(xtemp);
@ -599,7 +593,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(gtemp, w[i]);
// r_(jk+i+1) = r_(jk+i) - rho_(j+1) alpha_(jk+i+1) w_(jk+i)
w[i].Multiply(-rho * alpha, temp);
w[i].Multiply(-rho*alpha, temp);
residuals.Add(temp, temp2);
temp2.CopyTo(residuals);
@ -626,7 +620,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="maximumNumberOfStartingVectors">Maximum number</param>
/// <param name="numberOfVariables">Number of variables</param>
/// <returns>Number of starting vectors to create</returns>
private static int NumberOfStartingVectorsToCreate(int maximumNumberOfStartingVectors, int numberOfVariables)
static int NumberOfStartingVectorsToCreate(int maximumNumberOfStartingVectors, int numberOfVariables)
{
// Create no more starting vectors than the size of the problem - 1
return Math.Min(maximumNumberOfStartingVectors, (numberOfVariables - 1));
@ -643,7 +637,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// the <paramref name="numberOfVariables"/> is smaller than
/// the <paramref name="maximumNumberOfStartingVectors"/>.
/// </returns>
private static IList<Vector> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables)
static IList<Vector> CreateStartingVectors(int maximumNumberOfStartingVectors, int numberOfVariables)
{
// Create no more starting vectors than the size of the problem - 1
// Get random values and then orthogonalize them with
@ -662,7 +656,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
var samplesIm = distribution.Samples().Take(matrix.RowCount).ToArray();
for (int j = 0; j < matrix.RowCount; j++)
{
samples[j] = new Complex32((float)samplesRe[j], (float)samplesIm[j]);
samples[j] = new Complex32((float) samplesRe[j], (float) samplesIm[j]);
}
// Set the column
@ -677,10 +671,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
var result = new List<Vector>();
for (var i = 0; i < orthogonalMatrix.ColumnCount; i++)
{
result.Add((Vector)orthogonalMatrix.Column(i));
result.Add((Vector) orthogonalMatrix.Column(i));
// Normalize the result vector
result[i].Multiply(1 / result[i].Norm(2).Real, result[i]);
result[i].Multiply(1/result[i].L2Norm().Real, result[i]);
}
return result;
@ -692,7 +686,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="arraySize">Number of vectors</param>
/// <param name="vectorSize">Size of each vector</param>
/// <returns>Array of random vectors</returns>
private static Vector[] CreateVectorArray(int arraySize, int vectorSize)
static Vector[] CreateVectorArray(int arraySize, int vectorSize)
{
var result = new Vector[arraySize];
for (var i = 0; i < result.Length; i++)
@ -710,7 +704,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="residual">Residual <see cref="Vector"/> data.</param>
/// <param name="x">x <see cref="Vector"/> data.</param>
/// <param name="b">b <see cref="Vector"/> data.</param>
private static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
static void CalculateTrueResidual(Matrix matrix, Vector residual, Vector x, Vector b)
{
// -Ax = residual
matrix.Multiply(x, residual);
@ -728,7 +722,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns>
private bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
bool ShouldContinue(int iterationNumber, Vector result, Vector source, Vector residuals)
{
if (_hasBeenStopped)
{
@ -764,7 +758,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
throw new ArgumentNullException("input");
}
var result = (Matrix)matrix.CreateMatrix(input.RowCount, input.ColumnCount);
var result = (Matrix) matrix.CreateMatrix(input.RowCount, input.ColumnCount);
Solve(matrix, input, result);
return result;
}
@ -800,7 +794,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
for (var column = 0; column < input.ColumnCount; column++)
{
var solution = Solve(matrix, (Vector)input.Column(column));
var solution = Solve(matrix, (Vector) input.Column(column));
foreach (var element in solution.GetIndexedEnumerator())
{
result.At(element.Item1, column, element.Item2);

12
src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/TFQMR.cs

@ -282,15 +282,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
var temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.Norm(2);
// Define the scalars
Complex32 alpha = 0;
Complex32 eta = 0;
float theta = 0;
var tau = startNorm.Real;
// Initialize
var tau = input.L2Norm().Real;
Complex32 rho = tau*tau;
// Calculate the initial values for v
@ -311,7 +309,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
if (IsEven(iterationNumber))
{
// sigma = (v, r)
var sigma = v.DotProduct(r.Conjugate());
var sigma = r.ConjugateDotProduct(v);
if (sigma.Real.AlmostEqual(0, 1) && sigma.Imaginary.AlmostEqual(0, 1))
{
// FAIL HERE
@ -349,7 +347,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
yinternal.Add(temp, d);
// theta = ||pseudoResiduals||_2 / tau
theta = pseudoResiduals.Norm(2).Real/tau;
theta = pseudoResiduals.L2Norm().Real/tau;
var c = 1/(float) Math.Sqrt(1 + (theta*theta));
// tau = tau * theta * c
@ -392,7 +390,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
break;
}
var rhoNew = pseudoResiduals.DotProduct(r.Conjugate());
var rhoNew = r.ConjugateDotProduct(pseudoResiduals);
var beta = rhoNew/rho;
// Update rho for the next loop

2
src/Numerics/LinearAlgebra/Complex32/Solvers/Preconditioners/Ilutp.cs

@ -389,7 +389,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Preconditioners
// pivot the row
PivotRow(workVector);
var vectorNorm = workVector.Norm(Double.PositiveInfinity);
var vectorNorm = workVector.InfinityNorm();
// for j = 1, .. , i - 1)
for (var j = 0; j < i; j++)

2
src/Numerics/LinearAlgebra/Complex32/Solvers/StopCriterium/DivergenceStopCriterium.cs

@ -250,7 +250,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.StopCriterium
// Store the infinity norms of both the solution and residual vectors
// These values will be used to calculate the relative drop in residuals later on.
_residualHistory[_residualHistory.Length - 1] = residualVector.Norm(Double.PositiveInfinity).Real;
_residualHistory[_residualHistory.Length - 1] = residualVector.InfinityNorm().Real;
// Check if we have NaN's. If so we've gone way beyond normal divergence.
// Stop the iteration.

4
src/Numerics/LinearAlgebra/Complex32/Solvers/StopCriterium/FailureStopCriterium.cs

@ -105,8 +105,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.StopCriterium
}
// Store the infinity norms of both the solution and residual vectors
var residualNorm = residualVector.Norm(Double.PositiveInfinity);
var solutionNorm = solutionVector.Norm(Double.PositiveInfinity);
var residualNorm = residualVector.InfinityNorm();
var solutionNorm = solutionVector.InfinityNorm();
if (Single.IsNaN(solutionNorm.Real) || Single.IsNaN(residualNorm.Real))
{

4
src/Numerics/LinearAlgebra/Complex32/Solvers/StopCriterium/ResidualStopCriterium.cs

@ -257,11 +257,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.StopCriterium
// Store the infinity norms of both the solution and residual vectors
// These values will be used to calculate the relative drop in residuals
// later on.
var residualNorm = residualVector.Norm(float.PositiveInfinity);
var residualNorm = residualVector.InfinityNorm();
// Check the residuals by calculating:
// ||r_i|| <= stop_tol * ||b||
var stopCriterium = ComputeStopCriterium(sourceVector.Norm(float.PositiveInfinity).Real);
var stopCriterium = ComputeStopCriterium(sourceVector.InfinityNorm().Real);
// First check that we have real numbers not NaN's.
// NaN's can occur when the iterative process diverges so we

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

@ -1046,9 +1046,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<Complex32> other, Matrix<Complex32> result)
protected override void DoPointwiseDivide(Matrix<Complex32> divisor, Matrix<Complex32> result)
{
result.Clear();
@ -1067,7 +1067,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
if (!values[j].IsZero())
{
result.At(i, columnIndices[j], values[j]/other.At(i, columnIndices[j]));
result.At(i, columnIndices[j], values[j]/divisor.At(i, columnIndices[j]));
}
}
}

122
src/Numerics/LinearAlgebra/Complex32/SparseVector.cs

@ -535,16 +535,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Computes the dot product between this vector and another vector.
/// </summary>
/// <param name="other">
/// The other vector to add.
/// </param>
/// <returns>s
/// The result of the addition.
/// </returns>
/// <param name="other">The other vector.</param>
/// <returns>The sum of a[i]*b[i] for all i.</returns>
protected override Complex32 DoDotProduct(Vector<Complex32> other)
{
var result = Complex32.Zero;
if (ReferenceEquals(this, other))
{
for (var i = 0; i < _storage.ValueCount; i++)
@ -559,7 +554,31 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
result += _storage.Values[i] * other.At(_storage.Indices[i]);
}
}
return result;
}
/// <summary>
/// Computes the dot product between the conjugate of this vector and another vector.
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>The sum of conj(a[i])*b[i] for all i.</returns>
protected override Complex32 DoConjugateDotProduct(Vector<Complex32> other)
{
var result = Complex32.Zero;
if (ReferenceEquals(this, other))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _storage.Values[i].Conjugate() * _storage.Values[i];
}
}
else
{
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _storage.Values[i].Conjugate() * other.At(_storage.Indices[i]);
}
}
return result;
}
@ -739,25 +758,58 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
result += _storage.Values[i];
}
return result;
}
/// <summary>
/// Computes the sum of the absolute value of the vector's elements.
/// Calculates the L1 norm of the vector, also known as Manhattan norm.
/// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns>
public override Complex32 SumMagnitudes()
/// <returns>The sum of the absolute values.</returns>
public override Complex32 L1Norm()
{
var result = 0.0f;
var result = 0f;
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _storage.Values[i].Magnitude;
}
return result;
}
/// <summary>
/// Calculates the infinity norm of the vector.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override Complex32 InfinityNorm()
{
return CommonParallel.Aggregate(0, _storage.ValueCount, i => _storage.Values[i].Magnitude, Math.Max, 0f);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override Complex32 Norm(double p)
{
if (p < 0d) throw new ArgumentOutOfRangeException("p");
if (_storage.ValueCount == 0)
{
return Complex32.Zero;
}
if (p == 1d) return L1Norm();
if (p == 2d) return L2Norm();
if (Double.IsPositiveInfinity(p)) return InfinityNorm();
var sum = 0d;
for (var index = 0; index < _storage.ValueCount; index++)
{
sum += Math.Pow(_storage.Values[index].Magnitude, p);
}
return (float)Math.Pow(sum, 1.0 / p);
}
/// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary>
@ -785,11 +837,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise multiply with this one.</param>
/// <param name="divisor">The vector to pointwise multiply with this one.</param>
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseDivide(Vector<Complex32> other, Vector<Complex32> result)
protected override void DoPointwiseDivide(Vector<Complex32> divisor, Vector<Complex32> result)
{
if (ReferenceEquals(this, other))
if (ReferenceEquals(this, divisor))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
@ -801,7 +853,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _storage.Indices[i];
result.At(index, _storage.Values[i] / other.At(index));
result.At(index, _storage.Values[i] / divisor.At(index));
}
}
}
@ -853,42 +905,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return OuterProduct(this, v);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override Complex32 Norm(double p)
{
if (1 > p)
{
throw new ArgumentOutOfRangeException("p");
}
if (_storage.ValueCount == 0)
{
return Complex32.Zero;
}
if (2.0 == p)
{
return _storage.Values.Aggregate(Complex32.Zero, SpecialFunctions.Hypotenuse).Magnitude;
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(0, _storage.ValueCount, i => _storage.Values[i].Magnitude, Math.Max, 0f);
}
var sum = 0.0;
for (var index = 0; index < _storage.ValueCount; index++)
{
sum += Math.Pow(_storage.Values[index].Magnitude, p);
}
return (float)Math.Pow(sum, 1.0 / p);
}
#region Parse Functions
/// <summary>

97
src/Numerics/LinearAlgebra/Complex32/Vector.cs

@ -135,27 +135,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Divides each element of the vector by a scalar and stores the result in the result vector.
/// </summary>
/// <param name="scalar">
/// <param name="divisor">
/// The scalar to divide with.
/// </param>
/// <param name="result">
/// The vector to store the result of the division.
/// </param>
protected override void DoDivide(Complex32 scalar, Vector<Complex32> result)
protected override void DoDivide(Complex32 divisor, Vector<Complex32> result)
{
DoMultiply(1 / scalar, result);
DoMultiply(1 / divisor, result);
}
/// <summary>
/// Divides a scalar by each element of the vector and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to divide.</param>
/// <param name="dividend">The scalar to divide.</param>
/// <param name="result">The vector to store the result of the division.</param>
protected override void DoDivideByThis(Complex32 scalar, Vector<Complex32> result)
protected override void DoDivideByThis(Complex32 dividend, Vector<Complex32> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, scalar / At(index));
result.At(index, dividend / At(index));
}
}
@ -175,22 +175,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise divide this one by.</param>
/// <param name="divisor">The vector to pointwise divide this one by.</param>
/// <param name="result">The vector to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Vector<Complex32> other, Vector<Complex32> result)
protected override void DoPointwiseDivide(Vector<Complex32> divisor, Vector<Complex32> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) / other.At(index));
result.At(index, At(index) / divisor.At(index));
}
}
/// <summary>
/// Pointwise modulus this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise modulus this one by.</param>
/// <param name="divisor">The vector to pointwise modulus this one by.</param>
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Vector<Complex32> other, Vector<Complex32> result)
protected override void DoPointwiseModulus(Vector<Complex32> divisor, Vector<Complex32> result)
{
throw new NotSupportedException();
}
@ -198,28 +198,37 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Computes the dot product between this vector and another vector.
/// </summary>
/// <param name="other">
/// The other vector to add.
/// </param>
/// <returns>s
/// The result of the addition.
/// </returns>
/// <param name="other">The other vector.</param>
/// <returns>The sum of a[i]*b[i] for all i.</returns>
protected override Complex32 DoDotProduct(Vector<Complex32> other)
{
var dot = Complex32.Zero;
for (var i = 0; i < Count; i++)
{
dot += At(i) * other.At(i);
}
return dot;
}
/// <summary>
/// Computes the dot product between the conjugate of this vector and another vector.
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>The sum of conj(a[i])*b[i] for all i.</returns>
protected override Complex32 DoConjugateDotProduct(Vector<Complex32> other)
{
var dot = Complex32.Zero;
for (var i = 0; i < Count; i++)
{
dot += At(i).Conjugate() * other.At(i);
}
return dot;
}
/// <summary>
/// Computes the modulus for each element of the vector for the given divisor.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulus(Complex32 divisor, Vector<Complex32> result)
{
@ -229,9 +238,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary>
/// Computes the modulus for the given dividend for each element of the vector.
/// </summary>
/// <param name="scalar">The dividend to use.</param>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulusByThis(Complex32 scalar, Vector<Complex32> result)
protected override void DoModulusByThis(Complex32 dividend, Vector<Complex32> result)
{
throw new NotSupportedException();
}
@ -303,31 +312,45 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override Complex32 Sum()
{
var sum = Complex32.Zero;
for (var i = 0; i < Count; i++)
{
sum += At(i);
}
return sum;
}
/// <summary>
/// Computes the sum of the absolute value of the vector's elements.
/// Calculates the L1 norm of the vector, also known as Manhattan norm.
/// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns>
public override Complex32 SumMagnitudes()
/// <returns>The sum of the absolute values.</returns>
public override Complex32 L1Norm()
{
var sum = Complex32.Zero;
for (var i = 0; i < Count; i++)
{
sum += At(i).Magnitude;
}
return sum;
}
/// <summary>
/// Calculates the L2 norm of the vector, also known as Euclidean norm.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override Complex32 L2Norm()
{
return DoConjugateDotProduct(this).SquareRoot();
}
/// <summary>
/// Calculates the infinity norm of the vector.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override Complex32 InfinityNorm()
{
return CommonParallel.Aggregate(0, Count, i => At(i).Magnitude, Math.Max, 0f);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
@ -339,24 +362,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// </returns>
public override Complex32 Norm(double p)
{
if (p < 0.0)
{
throw new ArgumentOutOfRangeException("p");
}
if (p < 0d) throw new ArgumentOutOfRangeException("p");
if (double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(0, Count, i => At(i).Magnitude, Math.Max, 0f);
}
var sum = 0.0;
if (p == 1d) return L1Norm();
if (p == 2d) return L2Norm();
if (Double.IsPositiveInfinity(p)) return InfinityNorm();
var sum = 0d;
for (var index = 0; index < Count; index++)
{
sum += Math.Pow(At(index).Magnitude, p);
}
return (float)Math.Pow(sum, 1.0 / p);
return (float) Math.Pow(sum, 1.0/p);
}
/// <summary>

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

@ -392,6 +392,30 @@ namespace MathNet.Numerics.LinearAlgebra.Double
#endregion
/// <summary>
/// Add a scalar to each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(double scalar, Matrix<double> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoAdd(scalar, result);
return;
}
CommonParallel.For(0, _values.Length, 4096, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] = _values[i] + scalar;
}
});
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>
@ -413,6 +437,30 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
}
/// <summary>
/// Subtracts a scalar from each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to subtract.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(double scalar, Matrix<double> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoSubtract(scalar, result);
return;
}
CommonParallel.For(0, _values.Length, 4096, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] = _values[i] - scalar;
}
});
}
/// <summary>
/// Subtracts another matrix from this matrix.
/// </summary>
@ -623,6 +671,24 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
}
/// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary>
/// <param name="divisor">The scalar to divide the matrix with.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(double divisor, Matrix<double> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoDivide(divisor, result);
}
else
{
Control.LinearAlgebraProvider.ScaleArray(1.0/divisor, _values, denseResult._values);
}
}
/// <summary>
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
/// </summary>
@ -646,16 +712,16 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<double> other, Matrix<double> result)
protected override void DoPointwiseDivide(Matrix<double> divisor, Matrix<double> result)
{
var denseOther = other as DenseMatrix;
var denseOther = divisor as DenseMatrix;
var denseResult = result as DenseMatrix;
if (denseOther == null || denseResult == null)
{
base.DoPointwiseDivide(other, result);
base.DoPointwiseDivide(divisor, result);
}
else
{
@ -692,6 +758,30 @@ namespace MathNet.Numerics.LinearAlgebra.Double
});
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulusByThis(double dividend, Matrix<double> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoModulusByThis(dividend, result);
return;
}
CommonParallel.For(0, _values.Length, 4096, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] = dividend%_values[i];
}
});
}
/// <summary>
/// Computes the trace of this matrix.
/// </summary>

110
src/Numerics/LinearAlgebra/Double/DenseVector.cs

@ -440,14 +440,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary>
/// Computes the dot product between this vector and another vector.
/// </summary>
/// <param name="other">The other vector to add.</param>
/// <returns>s
/// The result of the addition.</returns>
/// <param name="other">The other vector.</param>
/// <returns>The sum of a[i]*b[i] for all i.</returns>
protected override double DoDotProduct(Vector<double> other)
{
var denseVector = other as DenseVector;
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
return denseVector == null
? base.DoDotProduct(other)
: Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
}
/// <summary>
@ -667,31 +667,67 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override double Sum()
{
var sum = 0.0;
for (var index = 0; index < _length; index++)
{
sum += _values[index];
}
return sum;
}
/// <summary>
/// Computes the sum of the absolute value of the vector's elements.
/// Calculates the L1 norm of the vector, also known as Manhattan norm.
/// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns>
public override double SumMagnitudes()
/// <returns>The sum of the absolute values.</returns>
public override double L1Norm()
{
var sum = 0.0;
var sum = 0d;
for (var index = 0; index < _length; index++)
{
sum += Math.Abs(_values[index]);
}
return sum;
}
/// <summary>
/// Calculates the L2 norm of the vector, also known as Euclidean norm.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double L2Norm()
{
// TODO: native provider
return _values.Aggregate(0d, SpecialFunctions.Hypotenuse);
}
/// <summary>
/// Calculates the infinity norm of the vector.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double InfinityNorm()
{
return CommonParallel.Aggregate(_values, (i, v) => Math.Abs(v), Math.Max, 0d);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override double Norm(double p)
{
if (p < 0d) throw new ArgumentOutOfRangeException("p");
if (p == 1d) return L1Norm();
if (p == 2d) return L2Norm();
if (Double.IsPositiveInfinity(p)) return InfinityNorm();
var sum = 0d;
for (var index = 0; index < _length; index++)
{
sum += Math.Pow(Math.Abs(_values[index]), p);
}
return Math.Pow(sum, 1.0 / p);
}
/// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary>
@ -715,17 +751,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise divide this one by.</param>
/// <param name="divisor">The vector to pointwise divide this one by.</param>
/// <param name="result">The vector to store the result of the pointwise division.</param>
/// <remarks></remarks>
protected override void DoPointwiseDivide(Vector<double> other, Vector<double> result)
protected override void DoPointwiseDivide(Vector<double> divisor, Vector<double> result)
{
var denseOther = other as DenseVector;
var denseOther = divisor as DenseVector;
var denseResult = result as DenseVector;
if (denseOther == null || denseResult == null)
{
base.DoPointwiseDivide(other, result);
base.DoPointwiseDivide(divisor, result);
}
else
{
@ -780,46 +816,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return OuterProduct(this, v);
}
#region Vector Norms
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override double Norm(double p)
{
if (p < 0.0)
{
throw new ArgumentOutOfRangeException("p");
}
if (1.0 == p)
{
return SumMagnitudes();
}
if (2.0 == p)
{
return _values.Aggregate(0.0, SpecialFunctions.Hypotenuse);
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(_values, (i, v) => Math.Abs(v), Math.Max, 0d);
}
var sum = 0.0;
for (var index = 0; index < _length; index++)
{
sum += Math.Pow(Math.Abs(_values[index]), p);
}
return Math.Pow(sum, 1.0 / p);
}
#endregion
#region Parse Functions
/// <summary>

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

@ -28,17 +28,18 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.Distributions;
using MathNet.Numerics.LinearAlgebra.Generic;
using MathNet.Numerics.LinearAlgebra.Storage;
using MathNet.Numerics.Properties;
using MathNet.Numerics.Threading;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace MathNet.Numerics.LinearAlgebra.Double
{
using Distributions;
using Generic;
using Properties;
using Storage;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
/// <summary>
/// A matrix type for diagonal matrices.
/// </summary>
@ -1044,28 +1045,49 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(double divisor, Matrix<double> result)
{
var denseResult = result as DiagonalMatrix;
if (denseResult == null)
var diagonalResult = result as DiagonalMatrix;
if (diagonalResult == null)
{
base.DoModulus(divisor, result);
return;
}
else
{
if (!ReferenceEquals(this, result))
{
CopyTo(result);
}
for (var index = 0; index < _data.Length; index++)
CommonParallel.For(0, _data.Length, 4096, (a, b) =>
{
denseResult._data[index] %= divisor;
}
var r = diagonalResult._data;
for (var i = a; i < b; i++)
{
r[i] = _data[i]%divisor;
}
});
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulusByThis(double dividend, Matrix<double> result)
{
var diagonalResult = result as DiagonalMatrix;
if (diagonalResult == null)
{
base.DoModulusByThis(dividend, result);
return;
}
CommonParallel.For(0, _data.Length, 4096, (a, b) =>
{
var r = diagonalResult._data;
for (var i = a; i < b; i++)
{
r[i] = dividend%_data[i];
}
});
}
#region Static constructors for special matrices.

2
src/Numerics/LinearAlgebra/Double/Factorization/UserGramSchmidt.cs

@ -68,7 +68,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
for (var k = 0; k < MatrixQ.ColumnCount; k++)
{
var norm = MatrixQ.Column(k).Norm(2);
var norm = MatrixQ.Column(k).L2Norm();
if (norm == 0.0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);

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

@ -114,6 +114,22 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return norm;
}
/// <summary>
/// Add a scalar to each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(double scalar, Matrix<double> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + scalar);
}
}
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>
@ -131,6 +147,22 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
}
}
/// <summary>
/// Subtracts a scalar from each element of the vector and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to subtract.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(double scalar, Matrix<double> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - scalar);
}
}
}
/// <summary>
/// Subtracts another matrix from this matrix.
@ -188,11 +220,27 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary>
/// <param name="scalar">The scalar to divide the matrix with.</param>
/// <param name="divisor">The scalar to divide the matrix with.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(double scalar, Matrix<double> result)
protected override void DoDivide(double divisor, Matrix<double> result)
{
DoMultiply(1.0 / scalar, result);
DoMultiply(1.0 / divisor, result);
}
/// <summary>
/// Divides a scalar by each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="dividend">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivideByThis(double dividend, Matrix<double> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, dividend / At(i, j));
}
}
}
/// <summary>
@ -309,6 +357,38 @@ namespace MathNet.Numerics.LinearAlgebra.Double
CopyTo(result);
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(double divisor, Matrix<double> result)
{
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
result.At(row, column, At(row, column)%divisor);
}
}
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulusByThis(double dividend, Matrix<double> result)
{
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
result.At(row, column, dividend%At(row, column));
}
}
}
/// <summary>
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
/// </summary>
@ -320,7 +400,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j) * other.At(i, j));
result.At(i, j, At(i, j)*other.At(i, j));
}
}
}
@ -328,31 +408,31 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<double> other, Matrix<double> result)
protected override void DoPointwiseDivide(Matrix<double> divisor, Matrix<double> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j) / other.At(i, j));
result.At(i, j, At(i, j)/divisor.At(i, j));
}
}
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// Pointwise modulus this matrix with another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(double divisor, Matrix<double> result)
/// <param name="divisor">The pointwise denominator matrix to use</param>
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Matrix<double> divisor, Matrix<double> result)
{
for (var row = 0; row < RowCount; row++)
for (var j = 0; j < ColumnCount; j++)
{
for (var column = 0; column < ColumnCount; column++)
for (var i = 0; i < RowCount; i++)
{
result.At(row, column, At(row, column) % divisor);
result.At(i, j, At(i, j)%divisor.At(i, j));
}
}
}

2
src/Numerics/LinearAlgebra/Double/Solvers/Iterative/MlkBiCgStab.cs

@ -673,7 +673,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers.Iterative
result.Add((Vector)orthogonalMatrix.Column(i));
// Normalize the result vector
result[i].Multiply(1 / result[i].Norm(2), result[i]);
result[i].Multiply(1 / result[i].L2Norm(), result[i]);
}
return result;

10
src/Numerics/LinearAlgebra/Double/Solvers/Iterative/TFQMR.cs

@ -280,17 +280,15 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers.Iterative
var temp = new DenseVector(input.Count);
var temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.Norm(2);
// Define the scalars
double alpha = 0;
double eta = 0;
double theta = 0;
var tau = startNorm;
var rho = tau * tau;
// Initialize
var tau = input.L2Norm();
var rho = tau*tau;
// Calculate the initial values for v
// M temp = yEven
@ -348,7 +346,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers.Iterative
yinternal.Add(temp, d);
// theta = ||pseudoResiduals||_2 / tau
theta = pseudoResiduals.Norm(2) / tau;
theta = pseudoResiduals.L2Norm() / tau;
var c = 1 / Math.Sqrt(1 + (theta * theta));
// tau = tau * theta * c

2
src/Numerics/LinearAlgebra/Double/Solvers/Preconditioners/Ilutp.cs

@ -388,7 +388,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers.Preconditioners
// pivot the row
PivotRow(workVector);
var vectorNorm = workVector.Norm(Double.PositiveInfinity);
var vectorNorm = workVector.InfinityNorm();
// for j = 1, .. , i - 1)
for (var j = 0; j < i; j++)

2
src/Numerics/LinearAlgebra/Double/Solvers/StopCriterium/DivergenceStopCriterium.cs

@ -250,7 +250,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers.StopCriterium
// Store the infinity norms of both the solution and residual vectors
// These values will be used to calculate the relative drop in residuals later on.
_residualHistory[_residualHistory.Length - 1] = residualVector.Norm(Double.PositiveInfinity);
_residualHistory[_residualHistory.Length - 1] = residualVector.InfinityNorm();
// Check if we have NaN's. If so we've gone way beyond normal divergence.
// Stop the iteration.

4
src/Numerics/LinearAlgebra/Double/Solvers/StopCriterium/FailureStopCriterium.cs

@ -105,8 +105,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers.StopCriterium
}
// Store the infinity norms of both the solution and residual vectors
var residualNorm = residualVector.Norm(Double.PositiveInfinity);
var solutionNorm = solutionVector.Norm(Double.PositiveInfinity);
var residualNorm = residualVector.InfinityNorm();
var solutionNorm = solutionVector.InfinityNorm();
if (Double.IsNaN(solutionNorm) || Double.IsNaN(residualNorm))
{

4
src/Numerics/LinearAlgebra/Double/Solvers/StopCriterium/ResidualStopCriterium.cs

@ -257,11 +257,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers.StopCriterium
// Store the infinity norms of both the solution and residual vectors
// These values will be used to calculate the relative drop in residuals
// later on.
var residualNorm = residualVector.Norm(Double.PositiveInfinity);
var residualNorm = residualVector.InfinityNorm();
// Check the residuals by calculating:
// ||r_i|| <= stop_tol * ||b||
var stopCriterium = ComputeStopCriterium(sourceVector.Norm(Double.PositiveInfinity));
var stopCriterium = ComputeStopCriterium(sourceVector.InfinityNorm());
// First check that we have real numbers not NaN's.
// NaN's can occur when the iterative process diverges so we

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

@ -1045,9 +1045,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<double> other, Matrix<double> result)
protected override void DoPointwiseDivide(Matrix<double> divisor, Matrix<double> result)
{
result.Clear();
@ -1066,7 +1066,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
if (values[j] != 0d)
{
result.At(i, columnIndices[j], values[j]/other.At(i, columnIndices[j]));
result.At(i, columnIndices[j], values[j]/divisor.At(i, columnIndices[j]));
}
}
}

101
src/Numerics/LinearAlgebra/Double/SparseVector.cs

@ -497,16 +497,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary>
/// Computes the dot product between this vector and another vector.
/// </summary>
/// <param name="other">
/// The other vector to add.
/// </param>
/// <returns>s
/// The result of the addition.
/// </returns>
/// <param name="other">The other vector.</param>
/// <returns>The sum of a[i]*b[i] for all i.</returns>
protected override double DoDotProduct(Vector<double> other)
{
var result = 0.0;
var result = 0d;
if (ReferenceEquals(this, other))
{
for (var i = 0; i < _storage.ValueCount; i++)
@ -521,7 +516,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
result += _storage.Values[i] * other.At(_storage.Indices[i]);
}
}
return result;
}
@ -775,25 +769,58 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
result += _storage.Values[i];
}
return result;
}
/// <summary>
/// Computes the sum of the absolute value of the vector's elements.
/// Calculates the L1 norm of the vector, also known as Manhattan norm.
/// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns>
public override double SumMagnitudes()
/// <returns>The sum of the absolute values.</returns>
public override double L1Norm()
{
double result = 0;
var result = 0d;
for (var i = 0; i < _storage.ValueCount; i++)
{
result += Math.Abs(_storage.Values[i]);
}
return result;
}
/// <summary>
/// Calculates the infinity norm of the vector.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double InfinityNorm()
{
return CommonParallel.Aggregate(0, _storage.ValueCount, i => Math.Abs(_storage.Values[i]), Math.Max, 0d);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override double Norm(double p)
{
if (p < 0d) throw new ArgumentOutOfRangeException("p");
if (_storage.ValueCount == 0)
{
return 0d;
}
if (p == 1d) return L1Norm();
if (p == 2d) return L2Norm();
if (Double.IsPositiveInfinity(p)) return InfinityNorm();
var sum = 0d;
for (var index = 0; index < _storage.ValueCount; index++)
{
sum += Math.Pow(Math.Abs(_storage.Values[index]), p);
}
return Math.Pow(sum, 1.0 / p);
}
/// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary>
@ -821,11 +848,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise multiply with this one.</param>
/// <param name="divisor">The vector to pointwise multiply with this one.</param>
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseDivide(Vector<double> other, Vector<double> result)
protected override void DoPointwiseDivide(Vector<double> divisor, Vector<double> result)
{
if (ReferenceEquals(this, other))
if (ReferenceEquals(this, divisor))
{
for (var i = 0; i < _storage.ValueCount; i++)
{
@ -837,7 +864,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _storage.Indices[i];
result.At(index, _storage.Values[i] / other.At(index));
result.At(index, _storage.Values[i] / divisor.At(index));
}
}
}
@ -886,42 +913,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return OuterProduct(this, v);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override double Norm(double p)
{
if (1 > p)
{
throw new ArgumentOutOfRangeException("p");
}
if (_storage.ValueCount == 0)
{
return 0.0;
}
if (2.0 == p)
{
return _storage.Values.Aggregate(0.0, SpecialFunctions.Hypotenuse);
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(0, _storage.ValueCount, i => Math.Abs(_storage.Values[i]), Math.Max, 0d);
}
var sum = 0.0;
for (var index = 0; index < _storage.ValueCount; index++)
{
sum += Math.Pow(Math.Abs(_storage.Values[index]), p);
}
return Math.Pow(sum, 1.0 / p);
}
#region Parse Functions
/// <summary>

118
src/Numerics/LinearAlgebra/Double/Vector.cs

@ -134,27 +134,27 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary>
/// Divides each element of the vector by a scalar and stores the result in the result vector.
/// </summary>
/// <param name="scalar">
/// <param name="divisor">
/// The scalar to divide with.
/// </param>
/// <param name="result">
/// The vector to store the result of the division.
/// </param>
protected override void DoDivide(double scalar, Vector<double> result)
protected override void DoDivide(double divisor, Vector<double> result)
{
DoMultiply(1 / scalar, result);
DoMultiply(1 / divisor, result);
}
/// <summary>
/// Divides a scalar by each element of the vector and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to divide.</param>
/// <param name="dividend">The scalar to divide.</param>
/// <param name="result">The vector to store the result of the division.</param>
protected override void DoDivideByThis(double scalar, Vector<double> result)
protected override void DoDivideByThis(double dividend, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, scalar / At(index));
result.At(index, dividend / At(index));
}
}
@ -174,67 +174,58 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise divide this one by.</param>
/// <param name="divisor">The vector to pointwise divide this one by.</param>
/// <param name="result">The vector to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Vector<double> other, Vector<double> result)
protected override void DoPointwiseDivide(Vector<double> divisor, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) / other.At(index));
result.At(index, At(index) / divisor.At(index));
}
}
/// <summary>
/// Pointwise modulus this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise modulus this one by.</param>
/// <param name="divisor">The vector to pointwise modulus this one by.</param>
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Vector<double> other, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) % other.At(index));
}
}
/// <summary>
/// Computes the modulus for the given dividend for each element of the vector.
/// </summary>
/// <param name="scalar">The dividend to use.</param>
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulusByThis(double scalar, Vector<double> result)
protected override void DoPointwiseModulus(Vector<double> divisor, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, scalar % At(index));
result.At(index, At(index) % divisor.At(index));
}
}
/// <summary>
/// Computes the dot product between this vector and another vector.
/// </summary>
/// <param name="other">
/// The other vector to add.
/// </param>
/// <returns>s
/// The result of the addition.
/// </returns>
/// <param name="other">The other vector.</param>
/// <returns>The sum of a[i]*b[i] for all i.</returns>
protected override double DoDotProduct(Vector<double> other)
{
var dot = 0.0;
for (var i = 0; i < Count; i++)
{
dot += At(i) * other.At(i);
}
return dot;
}
/// <summary>
/// Computes the dot product between the conjugate of this vector and another vector.
/// </summary>
/// <param name="other">The other vector.</param>
/// <returns>The sum of conj(a[i])*b[i] for all i.</returns>
protected override sealed double DoConjugateDotProduct(Vector<double> other)
{
return DoDotProduct(other);
}
/// <summary>
/// Computes the modulus for each element of the vector for the given divisor.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulus(double divisor, Vector<double> result)
{
@ -244,6 +235,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
}
/// <summary>
/// Computes the modulus for the given dividend for each element of the vector.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulusByThis(double dividend, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, dividend%At(index));
}
}
/// <summary>
/// Returns the value of the absolute minimum element.
/// </summary>
@ -311,31 +315,45 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override double Sum()
{
var sum = 0.0;
for (var i = 0; i < Count; i++)
{
sum += At(i);
}
return sum;
}
/// <summary>
/// Computes the sum of the absolute value of the vector's elements.
/// Calculates the L1 norm of the vector, also known as Manhattan norm.
/// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns>
public override double SumMagnitudes()
/// <returns>The sum of the absolute values.</returns>
public override double L1Norm()
{
var sum = 0.0;
for (var i = 0; i < Count; i++)
{
sum += Math.Abs(At(i));
}
return sum;
}
/// <summary>
/// Calculates the L2 norm of the vector, also known as Euclidean norm.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double L2Norm()
{
return Math.Sqrt(DoDotProduct(this));
}
/// <summary>
/// Calculates the infinity norm of the vector.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double InfinityNorm()
{
return CommonParallel.Aggregate(0, Count, i => Math.Abs(At(i)), Math.Max, 0d);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
@ -347,24 +365,18 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </returns>
public override double Norm(double p)
{
if (p < 0.0)
{
throw new ArgumentOutOfRangeException("p");
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(0, Count, i => Math.Abs(At(i)), Math.Max, 0d);
}
if (p < 0d) throw new ArgumentOutOfRangeException("p");
var sum = 0.0;
if (p == 1d) return L1Norm();
if (p == 2d) return L2Norm();
if (Double.IsPositiveInfinity(p)) return InfinityNorm();
var sum = 0d;
for (var index = 0; index < Count; index++)
{
sum += Math.Pow(Math.Abs(At(index)), p);
}
return Math.Pow(sum, 1.0 / p);
return Math.Pow(sum, 1.0/p);
}
/// <summary>

535
src/Numerics/LinearAlgebra/Generic/Matrix.Arithmetic.cs

@ -28,13 +28,12 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using MathNet.Numerics.LinearAlgebra.Generic.Factorization;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Generic
{
using System;
using Factorization;
using Properties;
/// <summary>
/// Defines the base class for <c>Matrix</c> classes.
/// </summary>
@ -62,6 +61,13 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// <param name="result">The result of the conjugation.</param>
protected abstract void DoConjugate(Matrix<T> result);
/// <summary>
/// Add a scalar to each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the addition.</param>
protected abstract void DoAdd(T scalar, Matrix<T> result);
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>
@ -71,6 +77,24 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
protected abstract void DoAdd(Matrix<T> other, Matrix<T> result);
/// <summary>
/// Subtracts a scalar from each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="scalar">The scalar to subtract.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected abstract void DoSubtract(T scalar, Matrix<T> result);
/// <summary>
/// Subtracts each element of the matrix from a scalar and stores the result in the result matrix.
/// </summary>
/// <param name="scalar">The scalar to subtract from.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected virtual void DoSubtractFrom(T scalar, Matrix<T> result)
{
DoNegate(result);
result.DoAdd(scalar, result);
}
/// <summary>
/// Subtracts another matrix from this matrix.
/// </summary>
@ -123,17 +147,31 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary>
/// <param name="scalar">The scalar to divide the matrix with.</param>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected abstract void DoDivide(T divisor, Matrix<T> result);
/// <summary>
/// Divides a scalar by each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected abstract void DoDivide(T scalar, Matrix<T> result);
protected abstract void DoDivideByThis(T dividend, Matrix<T> result);
/// <summary>
/// Computes the modulus for each element of the matrix.
/// Computes the modulus for the given divisor each element of the matrix.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected abstract void DoModulus(T divisor, Matrix<T> result);
/// <summary>
/// Computes the modulus for the given dividend for each element of the matrix.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">A vector to store the results in.</param>
protected abstract void DoModulusByThis(T dividend, Matrix<T> result);
/// <summary>
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
/// </summary>
@ -144,9 +182,63 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The pointwise denominator matrix to use.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected abstract void DoPointwiseDivide(Matrix<T> other, Matrix<T> result);
protected abstract void DoPointwiseDivide(Matrix<T> divisor, Matrix<T> result);
/// <summary>
/// Pointwise modulus this matrix with another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="divisor">The pointwise denominator matrix to use</param>
/// <param name="result">The result of the modulus.</param>
protected abstract void DoPointwiseModulus(Matrix<T> divisor, Matrix<T> result);
/// <summary>
/// Adds a scalar to each element of the matrix.
/// </summary>
/// <param name="scalar">The scalar to add.</param>
/// <returns>The result of the addition.</returns>
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
public Matrix<T> Add(T scalar)
{
if (scalar.Equals(Zero))
{
return Clone();
}
var result = CreateMatrix(RowCount, ColumnCount);
DoAdd(scalar, result);
return result;
}
/// <summary>
/// Adds a scalar to each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="scalar">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the addition.</param>
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null"/>.</exception>
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
public void Add(T scalar, Matrix<T> result)
{
if (result == null)
{
throw new ArgumentNullException("result");
}
if (result.RowCount != RowCount || result.ColumnCount != ColumnCount)
{
throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, result, "result");
}
if (scalar.Equals(Zero))
{
CopyTo(result);
return;
}
DoAdd(scalar, result);
}
/// <summary>
/// Adds another matrix to this matrix.
@ -204,6 +296,85 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
DoAdd(other, result);
}
/// <summary>
/// Subtracts a scalar from each element of the matrix.
/// </summary>
/// <param name="scalar">The scalar to subtract.</param>
/// <returns>A new matrix containing the subtraction of this matrix and the scalar.</returns>
public Matrix<T> Subtract(T scalar)
{
if (scalar.Equals(Zero))
{
return Clone();
}
var result = CreateMatrix(RowCount, ColumnCount);
DoSubtract(scalar, result);
return result;
}
/// <summary>
/// Subtracts a scalar from each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="scalar">The scalar to subtract.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
/// <exception cref="ArgumentNullException">If the result matrix is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="result"/> are not the same size.</exception>
public void Subtract(T scalar, Matrix<T> result)
{
if (result == null)
{
throw new ArgumentNullException("result");
}
if (result.RowCount != RowCount || result.ColumnCount != ColumnCount)
{
throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, result, "result");
}
if (scalar.Equals(Zero))
{
CopyTo(result);
return;
}
DoSubtract(scalar, result);
}
/// <summary>
/// Subtracts each element of the matrix from a scalar.
/// </summary>
/// <param name="scalar">The scalar to subtract from.</param>
/// <returns>A new matrix containing the subtraction of the scalar and this matrix.</returns>
public Matrix<T> SubtractFrom(T scalar)
{
var result = CreateMatrix(RowCount, ColumnCount);
DoSubtractFrom(scalar, result);
return result;
}
/// <summary>
/// Subtracts each element of the matrix from a scalar and stores the result in the result matrix.
/// </summary>
/// <param name="scalar">The scalar to subtract from.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
/// <exception cref="ArgumentNullException">If the result matrix is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="result"/> are not the same size.</exception>
public void SubtractFrom(T scalar, Matrix<T> result)
{
if (result == null)
{
throw new ArgumentNullException("result");
}
if (result.RowCount != RowCount || result.ColumnCount != ColumnCount)
{
throw DimensionsDontMatch<ArgumentOutOfRangeException>(this, result, "result");
}
DoSubtractFrom(scalar, result);
}
/// <summary>
/// Subtracts another matrix from this matrix.
/// </summary>
@ -381,6 +552,45 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
DoDivide(scalar, result);
}
/// <summary>
/// Divides a scalar by each element of the matrix.
/// </summary>
/// <param name="scalar">The scalar to divide.</param>
/// <returns>The result of the division.</returns>
public Matrix<T> DivideByThis(T scalar)
{
var result = CreateMatrix(RowCount, ColumnCount);
DoDivideByThis(scalar, result);
return result;
}
/// <summary>
/// Divides a scalar by each element of the matrix and places results into the result matrix.
/// </summary>
/// <param name="scalar">The scalar to divide.</param>
/// <param name="result">The matrix to store the result of the division.</param>
/// <exception cref="ArgumentNullException">If the result matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If the result matrix's dimensions are not the same as this matrix.</exception>
public void DivideByThis(T scalar, Matrix<T> result)
{
if (result == null)
{
throw new ArgumentNullException("result");
}
if (result.RowCount != RowCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension, "result");
}
if (result.ColumnCount != ColumnCount)
{
throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension, "result");
}
DoDivideByThis(scalar, result);
}
/// <summary>
/// Multiplies this matrix by a vector and returns the result.
/// </summary>
@ -843,66 +1053,77 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
}
/// <summary>
/// Pointwise multiplies this matrix with another matrix.
/// Computes the modulus (matrix % divisor) for each element of the matrix.
/// </summary>
/// <param name="other">The matrix to pointwise multiply with this one.</param>
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
/// <returns>A new matrix that is the pointwise multiplication of this matrix and <paramref name="other"/>.</returns>
public Matrix<T> PointwiseMultiply(Matrix<T> other)
/// <param name="divisor">The scalar denominator to use.</param>
/// <returns>A matrix containing the results.</returns>
public Matrix<T> Modulus(T divisor)
{
if (other == null)
var result = CreateMatrix(RowCount, ColumnCount);
DoModulus(divisor, result);
return result;
}
/// <summary>
/// Computes the modulus (matrix % divisor) for each element of the matrix.
/// </summary>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
public void Modulus(T divisor, Matrix<T> result)
{
if (result == null)
{
throw new ArgumentNullException("other");
throw new ArgumentNullException("result");
}
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
if (ColumnCount != result.ColumnCount || RowCount != result.RowCount)
{
throw DimensionsDontMatch<ArgumentException>(this, other, "other");
throw DimensionsDontMatch<ArgumentException>(this, result);
}
DoModulus(divisor, result);
}
/// <summary>
/// Computes the modulus (dividend % matrix) for each element of the matrix.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <returns>A matrix containing the results.</returns>
public Matrix<T> ModulusByThis(T dividend)
{
var result = CreateMatrix(RowCount, ColumnCount);
DoPointwiseMultiply(other, result);
DoModulusByThis(dividend, result);
return result;
}
/// <summary>
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
/// Computes the modulus (dividend % matrix) for each element of the matrix.
/// </summary>
/// <param name="other">The matrix to pointwise multiply with this one.</param>
/// <param name="result">The matrix to store the result of the pointwise multiplication.</param>
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentNullException">If the result matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="result"/> are not the same size.</exception>
public void PointwiseMultiply(Matrix<T> other, Matrix<T> result)
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
public void ModulusByThis(T dividend, Matrix<T> result)
{
if (other == null)
{
throw new ArgumentNullException("other");
}
if (result == null)
{
throw new ArgumentNullException("result");
}
if (ColumnCount != result.ColumnCount || RowCount != result.RowCount || ColumnCount != other.ColumnCount || RowCount != other.RowCount)
if (ColumnCount != result.ColumnCount || RowCount != result.RowCount)
{
throw DimensionsDontMatch<ArgumentException>(this, other, result);
throw DimensionsDontMatch<ArgumentException>(this, result);
}
DoPointwiseMultiply(other, result);
DoModulusByThis(dividend, result);
}
/// <summary>
/// Pointwise divide this matrix by another matrix.
/// Pointwise multiplies this matrix with another matrix.
/// </summary>
/// <param name="other">The matrix to pointwise subtract this one by.</param>
/// <param name="other">The matrix to pointwise multiply with this one.</param>
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
/// <returns>A new matrix that is the pointwise division of this matrix and <paramref name="other"/>.</returns>
public Matrix<T> PointwiseDivide(Matrix<T> other)
/// <returns>A new matrix that is the pointwise multiplication of this matrix and <paramref name="other"/>.</returns>
public Matrix<T> PointwiseMultiply(Matrix<T> other)
{
if (other == null)
{
@ -911,24 +1132,24 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
if (ColumnCount != other.ColumnCount || RowCount != other.RowCount)
{
throw DimensionsDontMatch<ArgumentException>(this, other);
throw DimensionsDontMatch<ArgumentException>(this, other, "other");
}
var result = CreateMatrix(RowCount, ColumnCount);
DoPointwiseDivide(other, result);
DoPointwiseMultiply(other, result);
return result;
}
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
/// <param name="other">The matrix to pointwise multiply with this one.</param>
/// <param name="result">The matrix to store the result of the pointwise multiplication.</param>
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentNullException">If the result matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="other"/> are not the same size.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="result"/> are not the same size.</exception>
public void PointwiseDivide(Matrix<T> other, Matrix<T> result)
public void PointwiseMultiply(Matrix<T> other, Matrix<T> result)
{
if (other == null)
{
@ -945,219 +1166,113 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
throw DimensionsDontMatch<ArgumentException>(this, other, result);
}
DoPointwiseDivide(other, result);
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <returns>A matrix containing the results.</returns>
public Matrix<T> Modulus(T divisor)
{
var result = CreateMatrix(RowCount, ColumnCount);
DoModulus(divisor, result);
return result;
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <param name="result">Matrix to store the results in.</param>
public void Modulus(T divisor, Matrix<T> result)
{
if (result == null)
{
throw new ArgumentNullException("result");
}
if (ColumnCount != result.ColumnCount || RowCount != result.RowCount)
{
throw DimensionsDontMatch<ArgumentException>(this, result);
}
DoModulus(divisor, result);
DoPointwiseMultiply(other, result);
}
/// <summary>
/// Returns a <strong>Matrix</strong> containing the same values of <paramref name="rightSide"/>.
/// Pointwise divide this matrix by another matrix.
/// </summary>
/// <param name="rightSide">The matrix to get the values from.</param>
/// <returns>A matrix containing a the same values as <paramref name="rightSide"/>.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator +(Matrix<T> rightSide)
/// <param name="divisor">The pointwise denominator matrix to use.</param>
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="divisor"/> are not the same size.</exception>
/// <returns>A new matrix that is the pointwise division of this matrix and <paramref name="divisor"/>.</returns>
public Matrix<T> PointwiseDivide(Matrix<T> divisor)
{
if (rightSide == null)
if (divisor == null)
{
throw new ArgumentNullException("rightSide");
throw new ArgumentNullException("divisor");
}
return rightSide.Clone();
}
/// <summary>
/// Negates each element of the matrix.
/// </summary>
/// <param name="rightSide">The matrix to negate.</param>
/// <returns>A matrix containing the negated values.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator -(Matrix<T> rightSide)
{
if (rightSide == null)
if (ColumnCount != divisor.ColumnCount || RowCount != divisor.RowCount)
{
throw new ArgumentNullException("rightSide");
throw DimensionsDontMatch<ArgumentException>(this, divisor);
}
return rightSide.Negate();
var result = CreateMatrix(RowCount, ColumnCount);
DoPointwiseDivide(divisor, result);
return result;
}
/// <summary>
/// Adds two matrices together and returns the results.
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <remarks>This operator will allocate new memory for the result. It will
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
/// is denser.</remarks>
/// <param name="leftSide">The left matrix to add.</param>
/// <param name="rightSide">The right matrix to add.</param>
/// <returns>The result of the addition.</returns>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator +(Matrix<T> leftSide, Matrix<T> rightSide)
/// <param name="divisor">The pointwise denominator matrix to use.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentNullException">If the result matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="divisor"/> are not the same size.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="result"/> are not the same size.</exception>
public void PointwiseDivide(Matrix<T> divisor, Matrix<T> result)
{
if (leftSide == null)
if (divisor == null)
{
throw new ArgumentNullException("leftSide");
throw new ArgumentNullException("divisor");
}
return leftSide.Add(rightSide);
}
/// <summary>
/// Subtracts two matrices together and returns the results.
/// </summary>
/// <remarks>This operator will allocate new memory for the result. It will
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
/// is denser.</remarks>
/// <param name="leftSide">The left matrix to subtract.</param>
/// <param name="rightSide">The right matrix to subtract.</param>
/// <returns>The result of the addition.</returns>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator -(Matrix<T> leftSide, Matrix<T> rightSide)
{
if (leftSide == null)
if (result == null)
{
throw new ArgumentNullException("leftSide");
throw new ArgumentNullException("result");
}
return leftSide.Subtract(rightSide);
}
/// <summary>
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
/// </summary>
/// <param name="leftSide">The matrix to multiply.</param>
/// <param name="rightSide">The constant to multiply the matrix by.</param>
/// <returns>The result of the multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator *(Matrix<T> leftSide, T rightSide)
{
if (leftSide == null)
if (ColumnCount != result.ColumnCount || RowCount != result.RowCount || ColumnCount != divisor.ColumnCount || RowCount != divisor.RowCount)
{
throw new ArgumentNullException("leftSide");
throw DimensionsDontMatch<ArgumentException>(this, divisor, result);
}
return leftSide.Multiply(rightSide);
DoPointwiseDivide(divisor, result);
}
/// <summary>
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
/// Pointwise modulus this matrix by another matrix.
/// </summary>
/// <param name="leftSide">The matrix to multiply.</param>
/// <param name="rightSide">The constant to multiply the matrix by.</param>
/// <returns>The result of the multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator *(T leftSide, Matrix<T> rightSide)
/// <param name="divisor">The pointwise denominator matrix to use.</param>
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="divisor"/> are not the same size.</exception>
/// <returns>A new matrix that is the pointwise modulus of this matrix and <paramref name="divisor"/>.</returns>
public Matrix<T> PointwiseModulus(Matrix<T> divisor)
{
if (rightSide == null)
if (divisor == null)
{
throw new ArgumentNullException("rightSide");
throw new ArgumentNullException("divisor");
}
return rightSide.Multiply(leftSide);
}
/// <summary>
/// Multiplies two matrices.
/// </summary>
/// <remarks>This operator will allocate new memory for the result. It will
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
/// is denser.</remarks>
/// <param name="leftSide">The left matrix to multiply.</param>
/// <param name="rightSide">The right matrix to multiply.</param>
/// <returns>The result of multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If the dimensions of <paramref name="leftSide"/> or <paramref name="rightSide"/> don't conform.</exception>
public static Matrix<T> operator *(Matrix<T> leftSide, Matrix<T> rightSide)
{
if (leftSide == null)
if (ColumnCount != divisor.ColumnCount || RowCount != divisor.RowCount)
{
throw new ArgumentNullException("leftSide");
throw DimensionsDontMatch<ArgumentException>(this, divisor);
}
return leftSide.Multiply(rightSide);
var result = CreateMatrix(RowCount, ColumnCount);
DoPointwiseModulus(divisor, result);
return result;
}
/// <summary>
/// Multiplies a <strong>Matrix</strong> and a Vector.
/// Pointwise modulus this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="leftSide">The matrix to multiply.</param>
/// <param name="rightSide">The vector to multiply.</param>
/// <returns>The result of multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator *(Matrix<T> leftSide, Vector<T> rightSide)
/// <param name="divisor">The pointwise denominator matrix to use.</param>
/// <param name="result">The matrix to store the result of the pointwise modulus.</param>
/// <exception cref="ArgumentNullException">If the other matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentNullException">If the result matrix is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="divisor"/> are not the same size.</exception>
/// <exception cref="ArgumentException">If this matrix and <paramref name="result"/> are not the same size.</exception>
public void PointwiseModulus(Matrix<T> divisor, Matrix<T> result)
{
if (leftSide == null)
if (divisor == null)
{
throw new ArgumentNullException("leftSide");
throw new ArgumentNullException("divisor");
}
return leftSide.Multiply(rightSide);
}
/// <summary>
/// Multiplies a Vector and a <strong>Matrix</strong>.
/// </summary>
/// <param name="leftSide">The vector to multiply.</param>
/// <param name="rightSide">The matrix to multiply.</param>
/// <returns>The result of multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator *(Vector<T> leftSide, Matrix<T> rightSide)
{
if (rightSide == null)
if (result == null)
{
throw new ArgumentNullException("rightSide");
throw new ArgumentNullException("result");
}
return rightSide.LeftMultiply(leftSide);
}
/// <summary>
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
/// </summary>
/// <param name="leftSide">The matrix to multiply.</param>
/// <param name="rightSide">The constant to multiply the matrix by.</param>
/// <returns>The result of the multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator %(Matrix<T> leftSide, T rightSide)
{
if (leftSide == null)
if (ColumnCount != result.ColumnCount || RowCount != result.RowCount || ColumnCount != divisor.ColumnCount || RowCount != divisor.RowCount)
{
throw new ArgumentNullException("leftSide");
throw DimensionsDontMatch<ArgumentException>(this, divisor, result);
}
return leftSide.Modulus(rightSide);
DoPointwiseModulus(divisor, result);
}
/// <summary>

386
src/Numerics/LinearAlgebra/Generic/Matrix.Operators.cs

@ -0,0 +1,386 @@
// <copyright file="Matrix.Arithmetic.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Runtime.CompilerServices;
namespace MathNet.Numerics.LinearAlgebra.Generic
{
/// <summary>
/// Defines the base class for <c>Matrix</c> classes.
/// </summary>
public abstract partial class Matrix<T>
{
/// <summary>
/// Returns a <strong>Matrix</strong> containing the same values of <paramref name="rightSide"/>.
/// </summary>
/// <param name="rightSide">The matrix to get the values from.</param>
/// <returns>A matrix containing a the same values as <paramref name="rightSide"/>.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator +(Matrix<T> rightSide)
{
if (rightSide == null)
{
throw new ArgumentNullException("rightSide");
}
return rightSide.Clone();
}
/// <summary>
/// Negates each element of the matrix.
/// </summary>
/// <param name="rightSide">The matrix to negate.</param>
/// <returns>A matrix containing the negated values.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator -(Matrix<T> rightSide)
{
if (rightSide == null)
{
throw new ArgumentNullException("rightSide");
}
return rightSide.Negate();
}
/// <summary>
/// Adds two matrices together and returns the results.
/// </summary>
/// <remarks>This operator will allocate new memory for the result. It will
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
/// is denser.</remarks>
/// <param name="leftSide">The left matrix to add.</param>
/// <param name="rightSide">The right matrix to add.</param>
/// <returns>The result of the addition.</returns>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator +(Matrix<T> leftSide, Matrix<T> rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Add(rightSide);
}
/// <summary>
/// Adds a scalar to each element of the matrix.
/// </summary>
/// <remarks>This operator will allocate new memory for the result. It will
/// choose the representation of the provided matrix.</remarks>
/// <param name="leftSide">The left matrix to add.</param>
/// <param name="rightSide">The scalar value to add.</param>
/// <returns>The result of the addition.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator +(Matrix<T> leftSide, T rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Add(rightSide);
}
/// <summary>
/// Adds a scalar to each element of the matrix.
/// </summary>
/// <remarks>This operator will allocate new memory for the result. It will
/// choose the representation of the provided matrix.</remarks>
/// <param name="leftSide">The scalar value to add.</param>
/// <param name="rightSide">The right matrix to add.</param>
/// <returns>The result of the addition.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator +(T leftSide, Matrix<T> rightSide)
{
if (rightSide == null)
{
throw new ArgumentNullException("rightSide");
}
return rightSide.Add(leftSide);
}
/// <summary>
/// Subtracts two matrices together and returns the results.
/// </summary>
/// <remarks>This operator will allocate new memory for the result. It will
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
/// is denser.</remarks>
/// <param name="leftSide">The left matrix to subtract.</param>
/// <param name="rightSide">The right matrix to subtract.</param>
/// <returns>The result of the subtraction.</returns>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator -(Matrix<T> leftSide, Matrix<T> rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Subtract(rightSide);
}
/// <summary>
/// Subtracts a scalar from each element of a matrix.
/// </summary>
/// <remarks>This operator will allocate new memory for the result. It will
/// choose the representation of the provided matrix.</remarks>
/// <param name="leftSide">The left matrix to subtract.</param>
/// <param name="rightSide">The scalar value to subtract.</param>
/// <returns>The result of the subtraction.</returns>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator -(Matrix<T> leftSide, T rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Subtract(rightSide);
}
/// <summary>
/// Substracts each element of a matrix from a scalar.
/// </summary>
/// <remarks>This operator will allocate new memory for the result. It will
/// choose the representation of the provided matrix.</remarks>
/// <param name="leftSide">The scalar value to subtract.</param>
/// <param name="rightSide">The right matrix to subtract.</param>
/// <returns>The result of the subtraction.</returns>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> don't have the same dimensions.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator -(T leftSide, Matrix<T> rightSide)
{
if (rightSide == null)
{
throw new ArgumentNullException("rightSide");
}
return rightSide.SubtractFrom(leftSide);
}
/// <summary>
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
/// </summary>
/// <param name="leftSide">The matrix to multiply.</param>
/// <param name="rightSide">The constant to multiply the matrix by.</param>
/// <returns>The result of the multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator *(Matrix<T> leftSide, T rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Multiply(rightSide);
}
/// <summary>
/// Multiplies a <strong>Matrix</strong> by a constant and returns the result.
/// </summary>
/// <param name="leftSide">The matrix to multiply.</param>
/// <param name="rightSide">The constant to multiply the matrix by.</param>
/// <returns>The result of the multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Matrix<T> operator *(T leftSide, Matrix<T> rightSide)
{
if (rightSide == null)
{
throw new ArgumentNullException("rightSide");
}
return rightSide.Multiply(leftSide);
}
/// <summary>
/// Multiplies two matrices.
/// </summary>
/// <remarks>This operator will allocate new memory for the result. It will
/// choose the representation of either <paramref name="leftSide"/> or <paramref name="rightSide"/> depending on which
/// is denser.</remarks>
/// <param name="leftSide">The left matrix to multiply.</param>
/// <param name="rightSide">The right matrix to multiply.</param>
/// <returns>The result of multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
/// <exception cref="ArgumentException">If the dimensions of <paramref name="leftSide"/> or <paramref name="rightSide"/> don't conform.</exception>
public static Matrix<T> operator *(Matrix<T> leftSide, Matrix<T> rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Multiply(rightSide);
}
/// <summary>
/// Multiplies a <strong>Matrix</strong> and a Vector.
/// </summary>
/// <param name="leftSide">The matrix to multiply.</param>
/// <param name="rightSide">The vector to multiply.</param>
/// <returns>The result of multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator *(Matrix<T> leftSide, Vector<T> rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Multiply(rightSide);
}
/// <summary>
/// Multiplies a Vector and a <strong>Matrix</strong>.
/// </summary>
/// <param name="leftSide">The vector to multiply.</param>
/// <param name="rightSide">The matrix to multiply.</param>
/// <returns>The result of multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator *(Vector<T> leftSide, Matrix<T> rightSide)
{
if (rightSide == null)
{
throw new ArgumentNullException("rightSide");
}
return rightSide.LeftMultiply(leftSide);
}
/// <summary>
/// Divides a scalar with a matrix.
/// </summary>
/// <param name="dividend">The scalar to divide.</param>
/// <param name="divisor">The matrix.</param>
/// <returns>The result of the division.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="divisor"/> is <see langword="null" />.</exception>
public static Matrix<T> operator /(T dividend, Matrix<T> divisor)
{
if (divisor == null)
{
throw new ArgumentNullException("divisor");
}
return divisor.DivideByThis(dividend);
}
/// <summary>
/// Divides a matrix with a scalar.
/// </summary>
/// <param name="dividend">The matrix to divide.</param>
/// <param name="divisor">The scalar value.</param>
/// <returns>The result of the division.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="dividend"/> is <see langword="null" />.</exception>
public static Matrix<T> operator /(Matrix<T> dividend, T divisor)
{
if (dividend == null)
{
throw new ArgumentNullException("dividend");
}
return dividend.Divide(divisor);
}
/// <summary>
/// Computes the modulus of each element of the matrix of the given divisor.
/// </summary>
/// <param name="dividend">The matrix whose elements we want to compute the modulus of.</param>
/// <param name="divisor">The divisor to use.</param>
/// <returns>The result of the calculation</returns>
/// <exception cref="ArgumentNullException">If <paramref name="dividend"/> is <see langword="null" />.</exception>
public static Matrix<T> operator %(Matrix<T> dividend, T divisor)
{
if (dividend == null)
{
throw new ArgumentNullException("dividend");
}
return dividend.Modulus(divisor);
}
/// <summary>
/// Computes the modulus of the given dividend of each element of the matrix.
/// </summary>
/// <param name="dividend">The dividend we want to compute the modulus of.</param>
/// <param name="divisor">The matrix whose elements we want to use as divisor.</param>
/// <returns>The result of the calculation</returns>
/// <exception cref="ArgumentNullException">If <paramref name="divisor"/> is <see langword="null" />.</exception>
public static Matrix<T> operator %(T dividend, Matrix<T> divisor)
{
if (divisor == null)
{
throw new ArgumentNullException("dividend");
}
return divisor.ModulusByThis(dividend);
}
/// <summary>
/// Computes the pointwise modulus of each element of two matrices.
/// </summary>
/// <param name="dividend">The matrix whose elements we want to compute the modulus of.</param>
/// <param name="divisor">The divisor to use.</param>
/// <returns>The result of the calculation</returns>
/// <exception cref="ArgumentException">If <paramref name="dividend"/> and <paramref name="divisor"/> are not the same size.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="dividend"/> is <see langword="null" />.</exception>
public static Matrix<T> operator %(Matrix<T> dividend, Matrix<T> divisor)
{
if (dividend == null)
{
throw new ArgumentNullException("dividend");
}
return dividend.PointwiseModulus(divisor);
}
[SpecialName]
public static Matrix<T> op_DotMultiply(Matrix<T> x, Matrix<T> y)
{
return x.PointwiseMultiply(y);
}
[SpecialName]
public static Matrix<T> op_DotDivide(Matrix<T> dividend, Matrix<T> divisor)
{
return dividend.PointwiseDivide(divisor);
}
[SpecialName]
public static Vector<T> op_DotPercent(Vector<T> dividend, Vector<T> divisor)
{
return dividend.PointwiseModulus(divisor);
}
}
}

1002
src/Numerics/LinearAlgebra/Generic/Vector.Arithmetic.cs

File diff suppressed because it is too large

349
src/Numerics/LinearAlgebra/Generic/Vector.Operators.cs

@ -0,0 +1,349 @@
// <copyright file="Vector.Operators.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Runtime.CompilerServices;
namespace MathNet.Numerics.LinearAlgebra.Generic
{
public abstract partial class Vector<T>
{
/// <summary>
/// Returns a <strong>Vector</strong> containing the same values of <paramref name="rightSide"/>.
/// </summary>
/// <remarks>This method is included for completeness.</remarks>
/// <param name="rightSide">The vector to get the values from.</param>
/// <returns>A vector containing the same values as <paramref name="rightSide"/>.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator +(Vector<T> rightSide)
{
if (rightSide == null)
{
throw new ArgumentNullException("rightSide");
}
return rightSide.Clone();
}
/// <summary>
/// Returns a <strong>Vector</strong> containing the negated values of <paramref name="rightSide"/>.
/// </summary>
/// <param name="rightSide">The vector to get the values from.</param>
/// <returns>A vector containing the negated values as <paramref name="rightSide"/>.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator -(Vector<T> rightSide)
{
if (rightSide == null)
{
throw new ArgumentNullException("rightSide");
}
return rightSide.Negate();
}
/// <summary>
/// Adds two <strong>Vectors</strong> together and returns the results.
/// </summary>
/// <param name="leftSide">One of the vectors to add.</param>
/// <param name="rightSide">The other vector to add.</param>
/// <returns>The result of the addition.</returns>
/// <exception cref="ArgumentException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> are not the same size.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator +(Vector<T> leftSide, Vector<T> rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Add(rightSide);
}
/// <summary>
/// Adds a scalar to each element of a vector.
/// </summary>
/// <param name="leftSide">The vector to add to.</param>
/// <param name="rightSide">The scalar value to add.</param>
/// <returns>The result of the addition.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator +(Vector<T> leftSide, T rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Add(rightSide);
}
/// <summary>
/// Adds a scalar to each element of a vector.
/// </summary>
/// <param name="leftSide">The scalar value to add.</param>
/// <param name="rightSide">The vector to add to.</param>
/// <returns>The result of the addition.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator +(T leftSide, Vector<T> rightSide)
{
if (rightSide == null)
{
throw new ArgumentNullException("rightSide");
}
return rightSide.Add(leftSide);
}
/// <summary>
/// Subtracts two <strong>Vectors</strong> and returns the results.
/// </summary>
/// <param name="leftSide">The vector to subtract from.</param>
/// <param name="rightSide">The vector to subtract.</param>
/// <returns>The result of the subtraction.</returns>
/// <exception cref="ArgumentException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> are not the same size.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator -(Vector<T> leftSide, Vector<T> rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Subtract(rightSide);
}
/// <summary>
/// Subtracts a scalar from each element of a vector.
/// </summary>
/// <param name="leftSide">The vector to subtract from.</param>
/// <param name="rightSide">The scalar value to subtract.</param>
/// <returns>The result of the subtraction.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator -(Vector<T> leftSide, T rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Subtract(rightSide);
}
/// <summary>
/// Substracts each element of a vector from a scalar.
/// </summary>
/// <param name="leftSide">The scalar value to subtract from.</param>
/// <param name="rightSide">The vector to subtract.</param>
/// <returns>The result of the subtraction.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator -(T leftSide, Vector<T> rightSide)
{
if (rightSide == null)
{
throw new ArgumentNullException("rightSide");
}
return rightSide.SubtractFrom(leftSide);
}
/// <summary>
/// Multiplies a vector with a scalar.
/// </summary>
/// <param name="leftSide">The vector to scale.</param>
/// <param name="rightSide">The scalar value.</param>
/// <returns>The result of the multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator *(Vector<T> leftSide, T rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.Multiply(rightSide);
}
/// <summary>
/// Multiplies a vector with a scalar.
/// </summary>
/// <param name="leftSide">The scalar value.</param>
/// <param name="rightSide">The vector to scale.</param>
/// <returns>The result of the multiplication.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static Vector<T> operator *(T leftSide, Vector<T> rightSide)
{
if (rightSide == null)
{
throw new ArgumentNullException("rightSide");
}
return rightSide.Multiply(leftSide);
}
/// <summary>
/// Computes the dot product between two <strong>Vectors</strong>.
/// </summary>
/// <param name="leftSide">The left row vector.</param>
/// <param name="rightSide">The right column vector.</param>
/// <returns>The dot product between the two vectors.</returns>
/// <exception cref="ArgumentException">If <paramref name="leftSide"/> and <paramref name="rightSide"/> are not the same size.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="leftSide"/> or <paramref name="rightSide"/> is <see langword="null" />.</exception>
public static T operator *(Vector<T> leftSide, Vector<T> rightSide)
{
if (leftSide == null)
{
throw new ArgumentNullException("leftSide");
}
return leftSide.DotProduct(rightSide);
}
/// <summary>
/// Divides a scalar with a vector.
/// </summary>
/// <param name="dividend">The scalar to divide.</param>
/// <param name="divisor">The vector.</param>
/// <returns>The result of the division.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="divisor"/> is <see langword="null" />.</exception>
public static Vector<T> operator /(T dividend, Vector<T> divisor)
{
if (divisor == null)
{
throw new ArgumentNullException("divisor");
}
return divisor.DevideByThis(dividend);
}
/// <summary>
/// Divides a vector with a scalar.
/// </summary>
/// <param name="dividend">The vector to divide.</param>
/// <param name="divisor">The scalar value.</param>
/// <returns>The result of the division.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="dividend"/> is <see langword="null" />.</exception>
public static Vector<T> operator /(Vector<T> dividend, T divisor)
{
if (dividend == null)
{
throw new ArgumentNullException("dividend");
}
return dividend.Divide(divisor);
}
/// <summary>
/// Pointwise divides two <strong>Vectors</strong>.
/// </summary>
/// <param name="dividend">The vector to divide.</param>
/// <param name="divisor">The other vector.</param>
/// <returns>The result of the division.</returns>
/// <exception cref="ArgumentException">If <paramref name="dividend"/> and <paramref name="divisor"/> are not the same size.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="dividend"/> is <see langword="null" />.</exception>
public static Vector<T> operator /(Vector<T> dividend, Vector<T> divisor)
{
if (dividend == null)
{
throw new ArgumentNullException("dividend");
}
return dividend.PointwiseDivide(divisor);
}
/// <summary>
/// Computes the modulus of each element of the vector of the given divisor.
/// </summary>
/// <param name="dividend">The vector whose elements we want to compute the modulus of.</param>
/// <param name="divisor">The divisor to use.</param>
/// <returns>The result of the calculation</returns>
/// <exception cref="ArgumentNullException">If <paramref name="dividend"/> is <see langword="null" />.</exception>
public static Vector<T> operator %(Vector<T> dividend, T divisor)
{
if (dividend == null)
{
throw new ArgumentNullException("dividend");
}
return dividend.Modulus(divisor);
}
/// <summary>
/// Computes the modulus of the given dividend of each element of the vector.
/// </summary>
/// <param name="dividend">The dividend we want to compute the modulus of.</param>
/// <param name="divisor">The vector whose elements we want to use as divisor.</param>
/// <returns>The result of the calculation</returns>
/// <exception cref="ArgumentNullException">If <paramref name="dividend"/> is <see langword="null" />.</exception>
public static Vector<T> operator %(T dividend, Vector<T> divisor)
{
if (divisor == null)
{
throw new ArgumentNullException("divisor");
}
return divisor.ModulusByThis(dividend);
}
/// <summary>
/// Computes the pointwise modulus of each element of two vectors.
/// </summary>
/// <param name="dividend">The vector whose elements we want to compute the modulus of.</param>
/// <param name="divisor">The divisor to use.</param>
/// <returns>The result of the calculation</returns>
/// <exception cref="ArgumentException">If <paramref name="dividend"/> and <paramref name="divisor"/> are not the same size.</exception>
/// <exception cref="ArgumentNullException">If <paramref name="dividend"/> is <see langword="null" />.</exception>
public static Vector<T> operator %(Vector<T> dividend, Vector<T> divisor)
{
if (dividend == null)
{
throw new ArgumentNullException("dividend");
}
return dividend.PointwiseModulus(divisor);
}
[SpecialName]
public static Vector<T> op_DotMultiply(Vector<T> x, Vector<T> y)
{
return x.PointwiseMultiply(y);
}
[SpecialName]
public static Vector<T> op_DotDivide(Vector<T> dividend, Vector<T> divisor)
{
return dividend.PointwiseDivide(divisor);
}
[SpecialName]
public static Vector<T> op_DotPercent(Vector<T> dividend, Vector<T> divisor)
{
return dividend.PointwiseModulus(divisor);
}
}
}

1242
src/Numerics/LinearAlgebra/Generic/Vector.cs

File diff suppressed because it is too large

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

@ -392,6 +392,30 @@ namespace MathNet.Numerics.LinearAlgebra.Single
#endregion
/// <summary>
/// Add a scalar to each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(float scalar, Matrix<float> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoAdd(scalar, result);
return;
}
CommonParallel.For(0, _values.Length, 4096, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] = _values[i] + scalar;
}
});
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>
@ -413,6 +437,30 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
}
/// <summary>
/// Subtracts a scalar from each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to subtract.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(float scalar, Matrix<float> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoSubtract(scalar, result);
return;
}
CommonParallel.For(0, _values.Length, 4096, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] = _values[i] - scalar;
}
});
}
/// <summary>
/// Subtracts another matrix from this matrix.
/// </summary>
@ -623,6 +671,24 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
}
/// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary>
/// <param name="divisor">The scalar to divide the matrix with.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(float divisor, Matrix<float> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoDivide(divisor, result);
}
else
{
Control.LinearAlgebraProvider.ScaleArray(1.0f/divisor, _values, denseResult._values);
}
}
/// <summary>
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
/// </summary>
@ -646,16 +712,16 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<float> other, Matrix<float> result)
protected override void DoPointwiseDivide(Matrix<float> divisor, Matrix<float> result)
{
var denseOther = other as DenseMatrix;
var denseOther = divisor as DenseMatrix;
var denseResult = result as DenseMatrix;
if (denseOther == null || denseResult == null)
{
base.DoPointwiseDivide(other, result);
base.DoPointwiseDivide(divisor, result);
}
else
{
@ -692,6 +758,30 @@ namespace MathNet.Numerics.LinearAlgebra.Single
});
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulusByThis(float dividend, Matrix<float> result)
{
var denseResult = result as DenseMatrix;
if (denseResult == null)
{
base.DoModulusByThis(dividend, result);
return;
}
CommonParallel.For(0, _values.Length, 4096, (a, b) =>
{
var v = denseResult._values;
for (int i = a; i < b; i++)
{
v[i] = dividend%_values[i];
}
});
}
/// <summary>
/// Computes the trace of this matrix.
/// </summary>

113
src/Numerics/LinearAlgebra/Single/DenseVector.cs

@ -429,14 +429,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary>
/// Computes the dot product between this vector and another vector.
/// </summary>
/// <param name="other">The other vector to add.</param>
/// <returns>s
/// The result of the addition.</returns>
/// <param name="other">The other vector.</param>
/// <returns>The sum of a[i]*b[i] for all i.</returns>
protected override float DoDotProduct(Vector<float> other)
{
var denseVector = other as DenseVector;
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
return denseVector == null
? base.DoDotProduct(other)
: Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
}
/// <summary>
@ -655,32 +655,68 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <returns>The sum of the vector's elements.</returns>
public override float Sum()
{
var sum = 0.0f;
var sum = 0f;
for (var i = 0; i < _length; i++)
{
sum += _values[i];
}
return sum;
}
/// <summary>
/// Computes the sum of the absolute value of the vector's elements.
/// Calculates the L1 norm of the vector, also known as Manhattan norm.
/// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns>
public override float SumMagnitudes()
/// <returns>The sum of the absolute values.</returns>
public override float L1Norm()
{
var sum = 0.0f;
var sum = 0f;
for (var i = 0; i < _length; i++)
{
sum += Math.Abs(_values[i]);
}
return sum;
}
/// <summary>
/// Calculates the L2 norm of the vector, also known as Euclidean norm.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override float L2Norm()
{
// TODO: native provider
return _values.Aggregate(0f, SpecialFunctions.Hypotenuse);
}
/// <summary>
/// Calculates the infinity norm of the vector.
/// </summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override float InfinityNorm()
{
return CommonParallel.Aggregate(_values, (i, v) => Math.Abs(v), Math.Max, 0f);
}
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override float Norm(double p)
{
if (p < 0d) throw new ArgumentOutOfRangeException("p");
if (p == 1d) return L1Norm();
if (p == 2d) return L2Norm();
if (Double.IsPositiveInfinity(p)) return InfinityNorm();
var sum = 0d;
for (var index = 0; index < _length; index++)
{
sum += Math.Pow(Math.Abs(_values[index]), p);
}
return (float)Math.Pow(sum, 1.0 / p);
}
/// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary>
@ -704,17 +740,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary>
/// <param name="other">The vector to pointwise divide this one by.</param>
/// <param name="divisor">The vector to pointwise divide this one by.</param>
/// <param name="result">The vector to store the result of the pointwise division.</param>
/// <remarks></remarks>
protected override void DoPointwiseDivide(Vector<float> other, Vector<float> result)
protected override void DoPointwiseDivide(Vector<float> divisor, Vector<float> result)
{
var denseOther = other as DenseVector;
var denseOther = divisor as DenseVector;
var denseResult = result as DenseVector;
if (denseOther == null || denseResult == null)
{
base.DoPointwiseDivide(other, result);
base.DoPointwiseDivide(divisor, result);
}
else
{
@ -769,47 +805,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return OuterProduct(this, v);
}
#region Vector Norms
/// <summary>
/// Computes the p-Norm.
/// </summary>
/// <param name="p">The p value.</param>
/// <returns>Scalar <c>ret = (sum(abs(this[i])^p))^(1/p)</c></returns>
public override float Norm(double p)
{
if (p < 0.0)
{
throw new ArgumentOutOfRangeException("p");
}
if (1.0 == p)
{
return SumMagnitudes();
}
if (2.0 == p)
{
return _values.Aggregate(0f, SpecialFunctions.Hypotenuse);
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(_values, (i, v) => Math.Abs(v), Math.Max, 0f);
}
var sum = 0.0;
for (var index = 0; index < _length; index++)
{
sum += Math.Pow(Math.Abs(_values[index]), p);
}
return (float)Math.Pow(sum, 1.0 / p);
}
#endregion
#region Parse Functions
/// <summary>

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

@ -28,17 +28,18 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using MathNet.Numerics.Distributions;
using MathNet.Numerics.LinearAlgebra.Generic;
using MathNet.Numerics.LinearAlgebra.Storage;
using MathNet.Numerics.Properties;
using MathNet.Numerics.Threading;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace MathNet.Numerics.LinearAlgebra.Single
{
using Distributions;
using Generic;
using Properties;
using Storage;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
/// <summary>
/// A matrix type for diagonal matrices.
/// </summary>
@ -1044,28 +1045,49 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(float divisor, Matrix<float> result)
{
var denseResult = result as DiagonalMatrix;
if (denseResult == null)
var diagonalResult = result as DiagonalMatrix;
if (diagonalResult == null)
{
base.DoModulus(divisor, result);
return;
}
else
{
if (!ReferenceEquals(this, result))
{
CopyTo(result);
}
for (var index = 0; index < _data.Length; index++)
CommonParallel.For(0, _data.Length, 4096, (a, b) =>
{
denseResult._data[index] %= divisor;
}
var r = diagonalResult._data;
for (var i = a; i < b; i++)
{
r[i] = _data[i]%divisor;
}
});
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulusByThis(float dividend, Matrix<float> result)
{
var diagonalResult = result as DiagonalMatrix;
if (diagonalResult == null)
{
base.DoModulusByThis(dividend, result);
return;
}
CommonParallel.For(0, _data.Length, 4096, (a, b) =>
{
var r = diagonalResult._data;
for (var i = a; i < b; i++)
{
r[i] = dividend%_data[i];
}
});
}
#region Static constructors for special matrices.

2
src/Numerics/LinearAlgebra/Single/Factorization/UserGramSchmidt.cs

@ -68,7 +68,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
for (var k = 0; k < MatrixQ.ColumnCount; k++)
{
var norm = MatrixQ.Column(k).Norm(2);
var norm = MatrixQ.Column(k).L2Norm();
if (norm == 0.0)
{
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);

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

@ -114,6 +114,22 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return norm;
}
/// <summary>
/// Add a scalar to each element of the matrix and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(float scalar, Matrix<float> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + scalar);
}
}
}
/// <summary>
/// Adds another matrix to this matrix.
/// </summary>
@ -132,6 +148,22 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
}
/// <summary>
/// Subtracts a scalar from each element of the vector and stores the result in the result vector.
/// </summary>
/// <param name="scalar">The scalar to subtract.</param>
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(float scalar, Matrix<float> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - scalar);
}
}
}
/// <summary>
/// Subtracts another matrix from this matrix.
/// </summary>
@ -210,11 +242,27 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary>
/// <param name="scalar">The scalar to divide the matrix with.</param>
/// <param name="divisor">The scalar to divide the matrix with.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(float scalar, Matrix<float> result)
protected override void DoDivide(float divisor, Matrix<float> result)
{
DoMultiply(1.0f / scalar, result);
DoMultiply(1.0f / divisor, result);
}
/// <summary>
/// Divides a scalar by each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="dividend">The scalar to add.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivideByThis(float dividend, Matrix<float> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, dividend / At(i, j));
}
}
}
/// <summary>
@ -283,7 +331,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="divisor">The divisor to use.</param>
/// <param name="divisor">The scalar denominator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(float divisor, Matrix<float> result)
{
@ -296,6 +344,22 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
}
/// <summary>
/// Computes the modulus for each element of the matrix.
/// </summary>
/// <param name="dividend">The scalar numerator to use.</param>
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulusByThis(float dividend, Matrix<float> result)
{
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
result.At(row, column, dividend % At(row, column));
}
}
}
/// <summary>
/// Negate each element of this matrix and place the results into the result matrix.
/// </summary>
@ -336,7 +400,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j) * other.At(i, j));
result.At(i, j, At(i, j)*other.At(i, j));
}
}
}
@ -344,15 +408,31 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="other">The matrix to pointwise divide this one by.</param>
/// <param name="divisor">The matrix to pointwise divide this one by.</param>
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<float> other, Matrix<float> result)
protected override void DoPointwiseDivide(Matrix<float> divisor, Matrix<float> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j)/divisor.At(i, j));
}
}
}
/// <summary>
/// Pointwise modulus this matrix with another matrix and stores the result into the result matrix.
/// </summary>
/// <param name="divisor">The pointwise denominator matrix to use</param>
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Matrix<float> divisor, Matrix<float> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j) / other.At(i, j));
result.At(i, j, At(i, j)%divisor.At(i, j));
}
}
}

2
src/Numerics/LinearAlgebra/Single/Solvers/Iterative/MlkBiCgStab.cs

@ -676,7 +676,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers.Iterative
result.Add((Vector)orthogonalMatrix.Column(i));
// Normalize the result vector
result[i].Multiply(1 / result[i].Norm(2), result[i]);
result[i].Multiply(1 / result[i].L2Norm(), result[i]);
}
return result;

8
src/Numerics/LinearAlgebra/Single/Solvers/Iterative/TFQMR.cs

@ -281,15 +281,13 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers.Iterative
var temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.Norm(2);
// Define the scalars
float alpha = 0;
float eta = 0;
float theta = 0;
var tau = startNorm;
// Initialize
var tau = input.L2Norm();
var rho = tau*tau;
// Calculate the initial values for v
@ -348,7 +346,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers.Iterative
yinternal.Add(temp, d);
// theta = ||pseudoResiduals||_2 / tau
theta = pseudoResiduals.Norm(2)/tau;
theta = pseudoResiduals.L2Norm()/tau;
var c = 1/(float) Math.Sqrt(1 + (theta*theta));
// tau = tau * theta * c

2
src/Numerics/LinearAlgebra/Single/Solvers/Preconditioners/Ilutp.cs

@ -388,7 +388,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers.Preconditioners
// pivot the row
PivotRow(workVector);
var vectorNorm = workVector.Norm(Double.PositiveInfinity);
var vectorNorm = workVector.InfinityNorm();
// for j = 1, .. , i - 1)
for (var j = 0; j < i; j++)

2
src/Numerics/LinearAlgebra/Single/Solvers/StopCriterium/DivergenceStopCriterium.cs

@ -250,7 +250,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers.StopCriterium
// Store the infinity norms of both the solution and residual vectors
// These values will be used to calculate the relative drop in residuals later on.
_residualHistory[_residualHistory.Length - 1] = residualVector.Norm(Double.PositiveInfinity);
_residualHistory[_residualHistory.Length - 1] = residualVector.InfinityNorm();
// Check if we have NaN's. If so we've gone way beyond normal divergence.
// Stop the iteration.

4
src/Numerics/LinearAlgebra/Single/Solvers/StopCriterium/FailureStopCriterium.cs

@ -105,8 +105,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers.StopCriterium
}
// Store the infinity norms of both the solution and residual vectors
var residualNorm = residualVector.Norm(Double.PositiveInfinity);
var solutionNorm = solutionVector.Norm(Double.PositiveInfinity);
var residualNorm = residualVector.InfinityNorm();
var solutionNorm = solutionVector.InfinityNorm();
if (Double.IsNaN(solutionNorm) || Double.IsNaN(residualNorm))
{

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save