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. 16
      src/Numerics/Distributions/Continuous/Beta.cs
  8. 32
      src/Numerics/Distributions/Continuous/Cauchy.cs
  9. 19
      src/Numerics/Distributions/Continuous/Chi.cs
  10. 18
      src/Numerics/Distributions/Continuous/ChiSquare.cs
  11. 21
      src/Numerics/Distributions/Continuous/ContinuousUniform.cs
  12. 26
      src/Numerics/Distributions/Continuous/Erlang.cs
  13. 19
      src/Numerics/Distributions/Continuous/Exponential.cs
  14. 27
      src/Numerics/Distributions/Continuous/FisherSnedecor.cs
  15. 18
      src/Numerics/Distributions/Continuous/Gamma.cs
  16. 25
      src/Numerics/Distributions/Continuous/InverseGamma.cs
  17. 30
      src/Numerics/Distributions/Continuous/Laplace.cs
  18. 56
      src/Numerics/Distributions/Continuous/LogNormal.cs
  19. 67
      src/Numerics/Distributions/Continuous/Normal.cs
  20. 30
      src/Numerics/Distributions/Continuous/Pareto.cs
  21. 24
      src/Numerics/Distributions/Continuous/Rayleigh.cs
  22. 37
      src/Numerics/Distributions/Continuous/Stable.cs
  23. 21
      src/Numerics/Distributions/Continuous/StudentT.cs
  24. 17
      src/Numerics/Distributions/Continuous/Weibull.cs
  25. 16
      src/Numerics/Distributions/Discrete/Bernoulli.cs
  26. 19
      src/Numerics/Distributions/Discrete/Binomial.cs
  27. 18
      src/Numerics/Distributions/Discrete/Categorical.cs
  28. 25
      src/Numerics/Distributions/Discrete/ConwayMaxwellPoisson.cs
  29. 17
      src/Numerics/Distributions/Discrete/DiscreteUniform.cs
  30. 15
      src/Numerics/Distributions/Discrete/Geometric.cs
  31. 249
      src/Numerics/Distributions/Discrete/Hypergeometric.cs
  32. 20
      src/Numerics/Distributions/Discrete/NegativeBinomial.cs
  33. 16
      src/Numerics/Distributions/Discrete/Poisson.cs
  34. 25
      src/Numerics/Distributions/Discrete/Zipf.cs
  35. 82
      src/Numerics/Distributions/Multivariate/Dirichlet.cs
  36. 72
      src/Numerics/Distributions/Multivariate/InverseWishart.cs
  37. 87
      src/Numerics/Distributions/Multivariate/MatrixNormal.cs
  38. 60
      src/Numerics/Distributions/Multivariate/Multinomial.cs
  39. 138
      src/Numerics/Distributions/Multivariate/NormalGamma.cs
  40. 74
      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. 33
      src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/BiCgStab.cs
  47. 15
      src/Numerics/LinearAlgebra/Complex/Solvers/Iterative/GpBiCg.cs
  48. 69
      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. 32
      src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/BiCgStab.cs
  62. 14
      src/Numerics/LinearAlgebra/Complex32/Solvers/Iterative/GpBiCg.cs
  63. 68
      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. 95
      src/Numerics/LinearAlgebra/Complex32/Vector.cs
  72. 98
      src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
  73. 110
      src/Numerics/LinearAlgebra/Double/DenseVector.cs
  74. 52
      src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs
  75. 2
      src/Numerics/LinearAlgebra/Double/Factorization/UserGramSchmidt.cs
  76. 106
      src/Numerics/LinearAlgebra/Double/Matrix.cs
  77. 2
      src/Numerics/LinearAlgebra/Double/Solvers/Iterative/MlkBiCgStab.cs
  78. 8
      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. 116
      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. 1236
      src/Numerics/LinearAlgebra/Generic/Vector.cs
  91. 98
      src/Numerics/LinearAlgebra/Single/DenseMatrix.cs
  92. 113
      src/Numerics/LinearAlgebra/Single/DenseVector.cs
  93. 52
      src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs
  94. 2
      src/Numerics/LinearAlgebra/Single/Factorization/UserGramSchmidt.cs
  95. 94
      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 EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Readme", "Readme", "{C2F37492-38AE-4186-8A7F-17B0B080942C}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Readme", "Readme", "{C2F37492-38AE-4186-8A7F-17B0B080942C}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
AUTHORS.markdown = AUTHORS.markdown CONTRIBUTING.md = CONTRIBUTING.md
COPYRIGHT.markdown = COPYRIGHT.markdown CONTRIBUTORS.md = CONTRIBUTORS.md
README.markdown = README.markdown LICENSE.md = LICENSE.md
MAINTAINING.md = MAINTAINING.md
README.md = README.md
RELEASENOTES.md = RELEASENOTES.md
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples", "src\Examples\Examples.csproj", "{8239A6FF-1EF3-4DA4-A860-95C392DD6899}" 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 // 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); 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(); Console.WriteLine();
// 2. Distributuion properties: // 2. Distributuion properties:
@ -125,9 +125,9 @@ namespace Examples.DiscreteDistributionsExamples
// 5. Generate 100000 samples of the Hypergeometric(52, 13, 5) distribution and display histogram // 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"); Console.WriteLine(@"5. Generate 100000 samples of the Hypergeometric(52, 13, 5) distribution and display histogram");
hypergeometric.PopulationSize = 52; hypergeometric.Population = 52;
hypergeometric.M = 13; hypergeometric.Success = 13;
hypergeometric.N = 5; hypergeometric.Draws = 5;
for (var i = 0; i < data.Length; i++) for (var i = 0; i < data.Length; i++)
{ {
data[i] = hypergeometric.Sample(); 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"); Console.WriteLine(@"5. Normalize matrix columns: before normalize");
foreach (var keyValuePair in matrix.ColumnEnumerator()) 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(); Console.WriteLine();
@ -105,7 +105,7 @@ namespace Examples.LinearAlgebraExamples
Console.WriteLine(@"5. Normalize matrix columns: after normalize"); Console.WriteLine(@"5. Normalize matrix columns: after normalize");
foreach (var keyValuePair in normalized.ColumnEnumerator()) 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(); Console.WriteLine();
@ -114,7 +114,7 @@ namespace Examples.LinearAlgebraExamples
Console.WriteLine(@"6. Normalize matrix rows: before normalize"); Console.WriteLine(@"6. Normalize matrix rows: before normalize");
foreach (var keyValuePair in matrix.RowEnumerator()) 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(); Console.WriteLine();
@ -122,7 +122,7 @@ namespace Examples.LinearAlgebraExamples
Console.WriteLine(@"6. Normalize matrix rows: after normalize"); Console.WriteLine(@"6. Normalize matrix rows: after normalize");
foreach (var keyValuePair in normalized.RowEnumerator()) 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)) 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 smallM = DenseMatrix.OfArray( Array2D.create 2 2 0.3 )
let failingFoldBackM = DenseMatrix.init 2 3 (fun i j -> 1.0) let failingFoldBackM = DenseMatrix.init 2 3 (fun i j -> 1.0)
/// A small sparse matrix. /// A small sparse matrix.
let sparseM = SparseMatrix.ofListi 2 3 [(1,0,0.3)] 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) ) let largeM = DenseMatrix.OfArray( Array2D.init 100 100 (fun i j -> float i * 100.0 + float j) )
[<Test>] [<Test>]
@ -179,3 +179,13 @@ module MatrixTests =
[<Test>] [<Test>]
let ``Matrix.foldByRow`` () = let ``Matrix.foldByRow`` () =
Matrix.foldByRow (+) 0.0 smallM |> should equal (DenseVector.ofList [0.6;0.6] :> Vector<float>) 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>] [<Test>]
let ``Vector.insert`` () = 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>) 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;
}
}
}

16
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> /// <exception cref="ArgumentOutOfRangeException">If any of the Beta parameters are negative.</exception>
public Beta(double a, double b) 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); SetParameters(a, b);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -143,7 +156,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -54,27 +54,33 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <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 /// 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> /// </summary>
public Cauchy() public Cauchy() : this(0, 1)
: this(0, 1)
{ {
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Cauchy"/> class. /// Initializes a new instance of the <see cref="Cauchy"/> class.
/// </summary> /// </summary>
/// <param name="location"> /// <param name="location">The location parameter for the distribution.</param>
/// The location parameter for the distribution. /// <param name="scale">The scale parameter for the distribution.</param>
/// </param> /// <exception cref="ArgumentException">If <paramref name="scale"/> is negative.</exception>
/// <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) 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); SetParameters(location, scale);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -121,7 +127,6 @@ namespace MathNet.Numerics.Distributions
public double Location public double Location
{ {
get { return Median; } get { return Median; }
set { SetParameters(value, _scale); } set { SetParameters(value, _scale); }
} }
@ -131,7 +136,6 @@ namespace MathNet.Numerics.Distributions
public double Scale public double Scale
{ {
get { return _scale; } get { return _scale; }
set { SetParameters(Median, value); } set { SetParameters(Median, value); }
} }

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

@ -57,13 +57,22 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Chi"/> class. /// Initializes a new instance of the <see cref="Chi"/> class.
/// </summary> /// </summary>
/// <param name="dof"> /// <param name="dof">The degrees of freedom for the Chi distribution.</param>
/// The degrees of freedom for the Chi distribution.
/// </param>
public Chi(double dof) 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); SetParameters(dof);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -102,7 +111,6 @@ namespace MathNet.Numerics.Distributions
public double DegreesOfFreedom public double DegreesOfFreedom
{ {
get { return _dof; } get { return _dof; }
set { SetParameters(value); } set { SetParameters(value); }
} }
@ -123,7 +131,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -54,13 +54,22 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ChiSquare"/> class. /// Initializes a new instance of the <see cref="ChiSquare"/> class.
/// </summary> /// </summary>
/// <param name="dof"> /// <param name="dof">The degrees of freedom for the ChiSquare distribution.</param>
/// The degrees of freedom for the ChiSquare distribution.
/// </param>
public ChiSquare(double dof) 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); SetParameters(dof);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -94,7 +103,6 @@ namespace MathNet.Numerics.Distributions
public double DegreesOfFreedom public double DegreesOfFreedom
{ {
get { return Mean; } get { return Mean; }
set { SetParameters(value); } set { SetParameters(value); }
} }

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

@ -63,8 +63,7 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the ContinuousUniform class with lower bound 0 and upper bound 1. /// Initializes a new instance of the ContinuousUniform class with lower bound 0 and upper bound 1.
/// </summary> /// </summary>
public ContinuousUniform() public ContinuousUniform() : this(0.0, 1.0)
: 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> /// <exception cref="ArgumentException">If the upper bound is smaller than the lower bound.</exception>
public ContinuousUniform(double lower, double upper) 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); SetParameters(lower, upper);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -133,7 +145,6 @@ namespace MathNet.Numerics.Distributions
public double Lower public double Lower
{ {
get { return _lower; } get { return _lower; }
set { SetParameters(value, _upper); } set { SetParameters(value, _upper); }
} }
@ -143,7 +154,6 @@ namespace MathNet.Numerics.Distributions
public double Upper public double Upper
{ {
get { return _upper; } get { return _upper; }
set { SetParameters(_lower, value); } set { SetParameters(_lower, value); }
} }
@ -155,7 +165,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -61,16 +61,24 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Erlang"/> class. /// Initializes a new instance of the <see cref="Erlang"/> class.
/// </summary> /// </summary>
/// <param name="shape"> /// <param name="shape">The shape of the Erlang distribution.</param>
/// The shape of the Erlang distribution. /// <param name="invScale">The inverse scale of the Erlang distribution.</param>
/// </param>
/// <param name="invScale">
/// The inverse scale of the Erlang distribution.
/// </param>
public Erlang(int shape, double invScale) 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); SetParameters(shape, invScale);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -135,7 +143,6 @@ namespace MathNet.Numerics.Distributions
public int Shape public int Shape
{ {
get { return (int) _shape; } get { return (int) _shape; }
set { SetParameters(value, _invScale); } set { SetParameters(value, _invScale); }
} }
@ -145,7 +152,6 @@ namespace MathNet.Numerics.Distributions
public double Scale public double Scale
{ {
get { return 1.0/_invScale; } get { return 1.0/_invScale; }
set set
{ {
var invScale = 1.0/value; var invScale = 1.0/value;
@ -165,7 +171,6 @@ namespace MathNet.Numerics.Distributions
public double InvScale public double InvScale
{ {
get { return _invScale; } get { return _invScale; }
set { SetParameters(_shape, value); } set { SetParameters(_shape, value); }
} }
@ -186,7 +191,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -54,13 +54,22 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Exponential"/> class. /// Initializes a new instance of the <see cref="Exponential"/> class.
/// </summary> /// </summary>
/// <param name="lambda"> /// <param name="lambda">The lambda parameter of the Exponential distribution.</param>
/// The lambda parameter of the Exponential distribution.
/// </param>
public Exponential(double lambda) 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); SetParameters(lambda);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -104,7 +113,6 @@ namespace MathNet.Numerics.Distributions
public double Lambda public double Lambda
{ {
get { return _lambda; } get { return _lambda; }
set { SetParameters(value); } set { SetParameters(value); }
} }
@ -125,7 +133,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -59,16 +59,24 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="FisherSnedecor"/> class. /// Initializes a new instance of the <see cref="FisherSnedecor"/> class.
/// </summary> /// </summary>
/// <param name="d1"> /// <param name="d1">The first parameter - degree of freedom.</param>
/// The first parameter - degree of freedom. /// <param name="d2">The second parameter - degree of freedom.</param>
/// </param>
/// <param name="d2">
/// The second parameter - degree of freedom.
/// </param>
public FisherSnedecor(double d1, double d2) 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); SetParameters(d1, d2);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -114,7 +122,6 @@ namespace MathNet.Numerics.Distributions
public double DegreeOfFreedom1 public double DegreeOfFreedom1
{ {
get { return _d1; } get { return _d1; }
set { SetParameters(value, _d2); } set { SetParameters(value, _d2); }
} }
@ -124,7 +131,6 @@ namespace MathNet.Numerics.Distributions
public double DegreeOfFreedom2 public double DegreeOfFreedom2
{ {
get { return _d2; } get { return _d2; }
set { SetParameters(_d1, value); } set { SetParameters(_d1, value); }
} }
@ -145,12 +151,11 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)
{ {
throw new ArgumentNullException(Resources.InvalidDistributionParameters); throw new ArgumentNullException();
} }
_random = value; _random = value;

18
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> /// <param name="invScale">The inverse scale of the Gamma distribution.</param>
public Gamma(double shape, double invScale) 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); SetParameters(shape, invScale);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -147,7 +159,6 @@ namespace MathNet.Numerics.Distributions
public double Shape public double Shape
{ {
get { return _shape; } get { return _shape; }
set { SetParameters(value, _invScale); } set { SetParameters(value, _invScale); }
} }
@ -157,7 +168,6 @@ namespace MathNet.Numerics.Distributions
public double Scale public double Scale
{ {
get { return 1.0/_invScale; } get { return 1.0/_invScale; }
set set
{ {
var invScale = 1.0/value; var invScale = 1.0/value;
@ -177,7 +187,6 @@ namespace MathNet.Numerics.Distributions
public double InvScale public double InvScale
{ {
get { return _invScale; } get { return _invScale; }
set { SetParameters(_shape, value); } set { SetParameters(_shape, value); }
} }
@ -189,7 +198,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -60,16 +60,24 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="InverseGamma"/> class. /// Initializes a new instance of the <see cref="InverseGamma"/> class.
/// </summary> /// </summary>
/// <param name="shape"> /// <param name="shape">The shape (alpha) parameter of the inverse Gamma distribution.</param>
/// The shape (alpha) parameter of the inverse Gamma distribution. /// <param name="scale">The scale (beta) parameter of the inverse Gamma distribution.</param>
/// </param>
/// <param name="scale">
/// The scale (beta) parameter of the inverse Gamma distribution.
/// </param>
public InverseGamma(double shape, double scale) public InverseGamma(double shape, double scale)
{ {
SetParameters(shape, scale);
_random = new Random(); _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> /// <summary>
@ -124,7 +132,6 @@ namespace MathNet.Numerics.Distributions
public double Shape public double Shape
{ {
get { return _shape; } get { return _shape; }
set { SetParameters(value, _scale); } set { SetParameters(value, _scale); }
} }
@ -134,7 +141,6 @@ namespace MathNet.Numerics.Distributions
public double Scale public double Scale
{ {
get { return _scale; } get { return _scale; }
set { SetParameters(_shape, value); } set { SetParameters(_shape, value); }
} }
@ -155,7 +161,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -59,7 +59,6 @@ namespace MathNet.Numerics.Distributions
public double Location public double Location
{ {
get { return Mean; } get { return Mean; }
set { SetParameters(value, _scale); } set { SetParameters(value, _scale); }
} }
@ -69,7 +68,6 @@ namespace MathNet.Numerics.Distributions
public double Scale public double Scale
{ {
get { return _scale; } get { return _scale; }
set { SetParameters(Mean, value); } set { SetParameters(Mean, value); }
} }
@ -84,19 +82,26 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Laplace"/> class. /// Initializes a new instance of the <see cref="Laplace"/> class.
/// </summary> /// </summary>
/// <param name="location"> /// <param name="location">The location for the Laplace distribution.</param>
/// The location for the Laplace distribution. /// <param name="scale">The scale for the Laplace distribution.</param>
/// </param> /// <exception cref="ArgumentException">If <paramref name="scale"/> is negative.</exception>
/// <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) 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); SetParameters(location, scale);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -154,7 +159,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -24,11 +24,14 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using System.Linq;
using MathNet.Numerics.Properties;
using MathNet.Numerics.Statistics;
using System.Collections.Generic;
namespace MathNet.Numerics.Distributions namespace MathNet.Numerics.Distributions
{ {
using System; using System;
using System.Collections.Generic;
using Properties;
/// <summary> /// <summary>
/// Implements the univariate Log-Normal distribution. For details about this distribution, see /// 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"/> /// The distribution will be initialized with the default <seealso cref="System.Random"/>
/// random number generator. /// random number generator.
/// </summary> /// </summary>
/// <param name="mu"> /// <param name="mu">The mu of the logarithm of the distribution.</param>
/// The mu of the logarithm of the distribution. /// <param name="sigma">The standard deviation of the logarithm of the distribution.</param>
/// </param>
/// <param name="sigma">
/// The standard deviation of the logarithm of the distribution.
/// </param>
public LogNormal(double mu, double sigma) public LogNormal(double mu, double sigma)
{ {
_random = new Random();
SetParameters(mu, sigma); SetParameters(mu, sigma);
RandomSource = new Random(); }
/// <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);
}
/// <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> /// <summary>
@ -121,7 +156,6 @@ namespace MathNet.Numerics.Distributions
public double Mu public double Mu
{ {
get { return _mu; } get { return _mu; }
set { SetParameters(value, _sigma); } set { SetParameters(value, _sigma); }
} }
@ -131,7 +165,6 @@ namespace MathNet.Numerics.Distributions
public double Sigma public double Sigma
{ {
get { return _sigma; } get { return _sigma; }
set { SetParameters(_mu, value); } set { SetParameters(_mu, value); }
} }
@ -143,7 +176,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -24,11 +24,13 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using MathNet.Numerics.Properties;
using MathNet.Numerics.Statistics;
using System.Collections.Generic;
namespace MathNet.Numerics.Distributions namespace MathNet.Numerics.Distributions
{ {
using System; using System;
using System.Collections.Generic;
using Properties;
/// <summary> /// <summary>
/// Implements the univariate Normal (or Gaussian) distribution. For details about this distribution, see /// 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> /// <summary>
/// Initializes a new instance of the Normal class with a particular mean and standard deviation. The distribution will /// 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. /// 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> /// <param name="stddev">The standard deviation of the normal distribution.</param>
public Normal(double mean, double stddev) 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); SetParameters(mean, stddev);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -114,6 +140,15 @@ namespace MathNet.Numerics.Distributions
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> /// <summary>
/// A string representation of the distribution. /// A string representation of the distribution.
/// </summary> /// </summary>
@ -177,15 +212,12 @@ namespace MathNet.Numerics.Distributions
} }
} }
#region IDistribution implementation
/// <summary> /// <summary>
/// Gets or sets the random number generator which is used to draw random samples. /// Gets or sets the random number generator which is used to draw random samples.
/// </summary> /// </summary>
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)
@ -203,7 +235,6 @@ namespace MathNet.Numerics.Distributions
public double Mean public double Mean
{ {
get { return _mean; } get { return _mean; }
set { SetParameters(value, _stdDev); } set { SetParameters(value, _stdDev); }
} }
@ -213,7 +244,6 @@ namespace MathNet.Numerics.Distributions
public double Variance public double Variance
{ {
get { return _stdDev*_stdDev; } get { return _stdDev*_stdDev; }
set { SetParameters(_mean, Math.Sqrt(value)); } set { SetParameters(_mean, Math.Sqrt(value)); }
} }
@ -223,7 +253,6 @@ namespace MathNet.Numerics.Distributions
public double StdDev public double StdDev
{ {
get { return _stdDev; } get { return _stdDev; }
set { SetParameters(_mean, value); } set { SetParameters(_mean, value); }
} }
@ -243,10 +272,6 @@ namespace MathNet.Numerics.Distributions
get { return 0.0; } get { return 0.0; }
} }
#endregion
#region IContinuousDistribution implementation
/// <summary> /// <summary>
/// Gets the mode of the normal distribution. /// Gets the mode of the normal distribution.
/// </summary> /// </summary>
@ -280,7 +305,7 @@ namespace MathNet.Numerics.Distributions
} }
/// <summary> /// <summary>
/// Computes the density of the normal distribution. /// Computes the density of the normal distribution (PDF), i.e. dP(X &lt;= x)/dx.
/// </summary> /// </summary>
/// <param name="mean">The mean of the normal distribution.</param> /// <param name="mean">The mean of the normal distribution.</param>
/// <param name="sdev">The standard deviation of the normal distribution.</param> /// <param name="sdev">The standard deviation of the normal distribution.</param>
@ -293,7 +318,7 @@ namespace MathNet.Numerics.Distributions
} }
/// <summary> /// <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> /// </summary>
/// <param name="mean">The mean of the normal distribution.</param> /// <param name="mean">The mean of the normal distribution.</param>
/// <param name="sdev">The standard deviation of the normal distribution.</param> /// <param name="sdev">The standard deviation of the normal distribution.</param>
@ -306,7 +331,7 @@ namespace MathNet.Numerics.Distributions
} }
/// <summary> /// <summary>
/// Computes the density of the normal distribution. /// Computes the density of the normal distribution (PDF), i.e. dP(X &lt;= x)/dx.
/// </summary> /// </summary>
/// <param name="x">The location at which to compute the density.</param> /// <param name="x">The location at which to compute the density.</param>
/// <returns>the density at <paramref name="x"/>.</returns> /// <returns>the density at <paramref name="x"/>.</returns>
@ -316,7 +341,7 @@ namespace MathNet.Numerics.Distributions
} }
/// <summary> /// <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> /// </summary>
/// <param name="x">The location at which to compute the log density.</param> /// <param name="x">The location at which to compute the log density.</param>
/// <returns>the log density at <paramref name="x"/>.</returns> /// <returns>the log density at <paramref name="x"/>.</returns>
@ -326,7 +351,7 @@ namespace MathNet.Numerics.Distributions
} }
/// <summary> /// <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> /// </summary>
/// <param name="mean">The mean of the normal distribution.</param> /// <param name="mean">The mean of the normal distribution.</param>
/// <param name="sdev">The standard deviation of the normal distribution.</param> /// <param name="sdev">The standard deviation of the normal distribution.</param>
@ -338,7 +363,7 @@ namespace MathNet.Numerics.Distributions
} }
/// <summary> /// <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> /// </summary>
/// <param name="x">The location at which to compute the cumulative density.</param> /// <param name="x">The location at which to compute the cumulative density.</param>
/// <returns>the cumulative density at <paramref name="x"/>.</returns> /// <returns>the cumulative density at <paramref name="x"/>.</returns>
@ -347,8 +372,6 @@ namespace MathNet.Numerics.Distributions
return CumulativeDistribution(_mean, _stdDev, x); return CumulativeDistribution(_mean, _stdDev, x);
} }
#endregion
/// <summary> /// <summary>
/// Computes the inverse cumulative distribution function of the normal distribution. /// Computes the inverse cumulative distribution function of the normal distribution.
/// </summary> /// </summary>
@ -359,8 +382,6 @@ namespace MathNet.Numerics.Distributions
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> /// <summary>
/// Samples a pair of standard normal distributed random variables using the <i>Box-Muller</i> algorithm. /// Samples a pair of standard normal distributed random variables using the <i>Box-Muller</i> algorithm.
/// </summary> /// </summary>

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

@ -61,19 +61,26 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Pareto"/> class. /// Initializes a new instance of the <see cref="Pareto"/> class.
/// </summary> /// </summary>
/// <param name="scale"> /// <param name="scale">The scale parameter of the distribution.</param>
/// The scale parameter of the distribution. /// <param name="shape">The shape parameter of the distribution.</param>
/// </param> /// <exception cref="ArgumentException">If <paramref name="scale"/> or <paramref name="shape"/> are negative.</exception>
/// <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) 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); SetParameters(scale, shape);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -120,7 +127,6 @@ namespace MathNet.Numerics.Distributions
public double Scale public double Scale
{ {
get { return _scale; } get { return _scale; }
set { SetParameters(value, _shape); } set { SetParameters(value, _shape); }
} }
@ -130,7 +136,6 @@ namespace MathNet.Numerics.Distributions
public double Shape public double Shape
{ {
get { return _shape; } get { return _shape; }
set { SetParameters(_scale, value); } set { SetParameters(_scale, value); }
} }
@ -151,7 +156,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -57,16 +57,24 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Rayleigh"/> class. /// Initializes a new instance of the <see cref="Rayleigh"/> class.
/// </summary> /// </summary>
/// <param name="scale"> /// <param name="scale">The scale parameter of the distribution.</param>
/// The scale parameter of the distribution. /// <exception cref="ArgumentException">If <paramref name="scale"/> is negative.</exception>
/// </param>
/// <exception cref="ArgumentException">
/// If <paramref name="scale"/> is negative.
/// </exception>
public Rayleigh(double scale) 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); SetParameters(scale);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -110,7 +118,6 @@ namespace MathNet.Numerics.Distributions
public double Scale public double Scale
{ {
get { return _scale; } get { return _scale; }
set { SetParameters(value); } set { SetParameters(value); }
} }
@ -131,7 +138,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -72,22 +72,28 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Stable"/> class. /// Initializes a new instance of the <see cref="Stable"/> class.
/// </summary> /// </summary>
/// <param name="alpha"> /// <param name="alpha">The stability parameter of the distribution.</param>
/// The stability parameter of the distribution. /// <param name="beta">The skewness parameter of the distribution.</param>
/// </param> /// <param name="scale">The scale parameter of the distribution.</param>
/// <param name="beta"> /// <param name="location">The location parameter of the distribution.</param>
/// 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) 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); SetParameters(alpha, beta, scale, location);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -149,7 +155,6 @@ namespace MathNet.Numerics.Distributions
public double Alpha public double Alpha
{ {
get { return _alpha; } get { return _alpha; }
set { SetParameters(value, _beta, _scale, _location); } set { SetParameters(value, _beta, _scale, _location); }
} }
@ -159,7 +164,6 @@ namespace MathNet.Numerics.Distributions
public double Beta public double Beta
{ {
get { return _beta; } get { return _beta; }
set { SetParameters(_alpha, value, _scale, _location); } set { SetParameters(_alpha, value, _scale, _location); }
} }
@ -169,7 +173,6 @@ namespace MathNet.Numerics.Distributions
public double Scale public double Scale
{ {
get { return _scale; } get { return _scale; }
set { SetParameters(_alpha, _beta, value, _location); } set { SetParameters(_alpha, _beta, value, _location); }
} }
@ -179,7 +182,6 @@ namespace MathNet.Numerics.Distributions
public double Location public double Location
{ {
get { return _location; } get { return _location; }
set { SetParameters(_alpha, _beta, _scale, value); } set { SetParameters(_alpha, _beta, _scale, value); }
} }
@ -200,7 +202,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

21
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> /// <param name="dof">The degrees of freedom for the Student t-distribution.</param>
public StudentT(double location, double scale, double dof) 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); SetParameters(location, scale, dof);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -147,7 +162,6 @@ namespace MathNet.Numerics.Distributions
public double Location public double Location
{ {
get { return _location; } get { return _location; }
set { SetParameters(value, _scale, _dof); } set { SetParameters(value, _scale, _dof); }
} }
@ -157,7 +171,6 @@ namespace MathNet.Numerics.Distributions
public double Scale public double Scale
{ {
get { return _scale; } get { return _scale; }
set { SetParameters(_location, value, _dof); } set { SetParameters(_location, value, _dof); }
} }
@ -167,7 +180,6 @@ namespace MathNet.Numerics.Distributions
public double DegreesOfFreedom public double DegreesOfFreedom
{ {
get { return _dof; } get { return _dof; }
set { SetParameters(_location, _scale, value); } set { SetParameters(_location, _scale, value); }
} }
@ -179,7 +191,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

17
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> /// <param name="scale">The inverse scale of the Weibull distribution.</param>
public Weibull(double shape, double scale) 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); SetParameters(shape, scale);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -131,7 +143,6 @@ namespace MathNet.Numerics.Distributions
public double Shape public double Shape
{ {
get { return _shape; } get { return _shape; }
set { SetParameters(value, _scale); } set { SetParameters(value, _scale); }
} }
@ -141,7 +152,6 @@ namespace MathNet.Numerics.Distributions
public double Scale public double Scale
{ {
get { return _scale; } get { return _scale; }
set { SetParameters(_shape, value); } set { SetParameters(_shape, value); }
} }
@ -153,7 +163,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

16
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> /// <exception cref="ArgumentOutOfRangeException">If the Bernoulli parameter is not in the range [0,1].</exception>
public Bernoulli(double p) 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); SetParameters(p);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -108,7 +120,6 @@ namespace MathNet.Numerics.Distributions
public double P public double P
{ {
get { return _p; } get { return _p; }
set { SetParameters(value); } set { SetParameters(value); }
} }
@ -120,7 +131,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -66,8 +66,22 @@ namespace MathNet.Numerics.Distributions
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="n"/> is negative.</exception> /// <exception cref="ArgumentOutOfRangeException">If <paramref name="n"/> is negative.</exception>
public Binomial(double p, int n) 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); SetParameters(p, n);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -124,7 +138,6 @@ namespace MathNet.Numerics.Distributions
public double P public double P
{ {
get { return _p; } get { return _p; }
set { SetParameters(value, _n); } set { SetParameters(value, _n); }
} }
@ -134,7 +147,6 @@ namespace MathNet.Numerics.Distributions
public int N public int N
{ {
get { return _n; } get { return _n; }
set { SetParameters(_p, value); } set { SetParameters(_p, value); }
} }
@ -146,7 +158,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

18
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> /// <exception cref="ArgumentException">If any of the probabilities are negative or do not sum to one.</exception>
public Categorical(double[] probabilityMass) 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); SetParameters(probabilityMass);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -89,8 +102,8 @@ namespace MathNet.Numerics.Distributions
p[i] = histogram[i].Count; p[i] = histogram[i].Count;
} }
_random = new Random();
SetParameters(p); SetParameters(p);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -196,7 +209,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -87,16 +87,24 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ConwayMaxwellPoisson"/> class. /// Initializes a new instance of the <see cref="ConwayMaxwellPoisson"/> class.
/// </summary> /// </summary>
/// <param name="lambda"> /// <param name="lambda">The lambda parameter.</param>
/// The lambda parameter. /// <param name="nu">The nu parameter.</param>
/// </param>
/// <param name="nu">
/// The nu parameter.
/// </param>
public ConwayMaxwellPoisson(double lambda, double nu) 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); SetParameters(lambda, nu);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -144,7 +152,6 @@ namespace MathNet.Numerics.Distributions
public double Lambda public double Lambda
{ {
get { return _lambda; } get { return _lambda; }
set { SetParameters(value, _nu); } set { SetParameters(value, _nu); }
} }
@ -155,7 +162,6 @@ namespace MathNet.Numerics.Distributions
public double Nu public double Nu
{ {
get { return _nu; } get { return _nu; }
set { SetParameters(_lambda, value); } set { SetParameters(_lambda, value); }
} }
@ -178,7 +184,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

17
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> /// <param name="upper">Upper bound; must be at least as large as <paramref name="lower"/>.</param>
public DiscreteUniform(int lower, int upper) 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); SetParameters(lower, upper);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -118,7 +130,6 @@ namespace MathNet.Numerics.Distributions
public int LowerBound public int LowerBound
{ {
get { return _lower; } get { return _lower; }
set { SetParameters(value, _upper); } set { SetParameters(value, _upper); }
} }
@ -128,7 +139,6 @@ namespace MathNet.Numerics.Distributions
public int UpperBound public int UpperBound
{ {
get { return _upper; } get { return _upper; }
set { SetParameters(_lower, value); } set { SetParameters(_lower, value); }
} }
@ -140,7 +150,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

15
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> /// <exception cref="ArgumentOutOfRangeException">If the Geometric parameter is not in the range [0,1].</exception>
public Geometric(double p) 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); SetParameters(p);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -122,7 +134,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

249
src/Numerics/Distributions/Discrete/Hypergeometric.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics // http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com // http://mathnetnumerics.codeplex.com
// //
// Copyright (c) 2009-2010 Math.NET // Copyright (c) 2009-2013 Math.NET
// //
// Permission is hereby granted, free of charge, to any person // Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation // obtaining a copy of this software and associated documentation
@ -28,11 +28,12 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using MathNet.Numerics.Properties;
using System.Collections.Generic;
namespace MathNet.Numerics.Distributions namespace MathNet.Numerics.Distributions
{ {
using System; using System;
using System.Collections.Generic;
using Properties;
/// <summary> /// <summary>
/// This class implements functionality for the Hypergeometric distribution. This distribution is /// This class implements functionality for the Hypergeometric distribution. This distribution is
@ -50,19 +51,19 @@ namespace MathNet.Numerics.Distributions
public class Hypergeometric : IDiscreteDistribution public class Hypergeometric : IDiscreteDistribution
{ {
/// <summary> /// <summary>
/// The size of the population. /// The size of the population (N).
/// </summary> /// </summary>
int _populationSize; int _population;
/// <summary> /// <summary>
/// The m parameter of the distribution. /// The number successes within the population (K, M).
/// </summary> /// </summary>
int _m; int _success;
/// <summary> /// <summary>
/// The n parameter (number to draw) of the distribution. /// The number of draws without replacement (n).
/// </summary> /// </summary>
int _n; int _draws;
/// <summary> /// <summary>
/// The distribution's random number generator. /// The distribution's random number generator.
@ -72,48 +73,61 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the Hypergeometric class. /// Initializes a new instance of the Hypergeometric class.
/// </summary> /// </summary>
/// <param name="populationSize">The population size.</param> /// <param name="population">The size of the population (N).</param>
/// <param name="m">The m parameter of the distribution.</param> /// <param name="success">The number successes within the population (K, M).</param>
/// <param name="n">The n parameter of the distribution.</param> /// <param name="draws">The number of draws without replacement (n).</param>
public Hypergeometric(int populationSize, int m, int n) 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); _random = randomSource ?? new Random();
RandomSource = new Random(); SetParameters(population, success, draws);
} }
/// <summary> /// <summary>
/// Sets the parameters of the distribution after checking their validity. /// Sets the parameters of the distribution after checking their validity.
/// </summary> /// </summary>
/// <param name="total">The Total parameter of the distribution.</param> /// <param name="population">The size of the population (N).</param>
/// <param name="m">The m parameter of the distribution.</param> /// <param name="success">The number successes within the population (K, M).</param>
/// <param name="n">The n parameter of the distribution.</param> /// <param name="draws">The number of draws without replacement (n).</param>
void SetParameters(int total, int m, int n) 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); throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
} }
_populationSize = total; _population = population;
_m = m; _success = success;
_n = n; _draws = draws;
} }
/// <summary> /// <summary>
/// Checks whether the parameters of the distribution are valid. /// Checks whether the parameters of the distribution are valid.
/// </summary> /// </summary>
/// <param name="total">The Total parameter of the distribution.</param> /// <param name="population">The size of the population (N).</param>
/// <param name="m">The m parameter of the distribution.</param> /// <param name="success">The number successes within the population (K, M).</param>
/// <param name="n">The n parameter of the distribution.</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> /// <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; return false;
} }
if (m > total || n > total) if (success > population || draws > population)
{ {
return false; return false;
} }
@ -122,30 +136,60 @@ namespace MathNet.Numerics.Distributions
} }
/// <summary> /// <summary>
/// Gets or sets the population size. /// Gets or sets the size of the population (N).
/// </summary> /// </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 public int PopulationSize
{ {
get { return _populationSize; } get { return _population; }
set { SetParameters(value, _m, _n); } set { SetParameters(value, _success, _draws); }
} }
/// <summary> /// <summary>
/// Gets or sets the n parameter of the distribution. /// Gets or sets the number of draws without replacement (n).
/// </summary> /// </summary>
[Obsolete("Use Draws instead. Scheduled for removal in v3.0.")]
public int N public int N
{ {
get { return _n; } get { return _draws; }
set { SetParameters(_populationSize, value, _n); } set { SetParameters(_population, value, _draws); }
} }
/// <summary> /// <summary>
/// Gets or sets the m parameter of the distribution. /// Gets or sets the number successes within the population (K, M).
/// </summary> /// </summary>
[Obsolete("Use Success instead. Scheduled for removal in v3.0.")]
public int M public int M
{ {
get { return _m; } get { return _success; }
set { SetParameters(_populationSize, _m, value); } set { SetParameters(_population, _success, value); }
} }
/// <summary> /// <summary>
@ -156,18 +200,15 @@ namespace MathNet.Numerics.Distributions
/// </returns> /// </returns>
public override string ToString() public override string ToString()
{ {
return "Hypergeometric(N = " + _populationSize + ", m = " + _m + ", n = " + _n + ")"; return "Hypergeometric(N = " + _population + ", M = " + _success + ", n = " + _draws + ")";
} }
#region IDistribution Members
/// <summary> /// <summary>
/// Gets or sets the random number generator which is used to draw random samples. /// Gets or sets the random number generator which is used to draw random samples.
/// </summary> /// </summary>
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)
@ -184,7 +225,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double Mean public double Mean
{ {
get { return (double)_m * _n / _populationSize; } get { return (double) _success*_draws/_population; }
} }
/// <summary> /// <summary>
@ -192,7 +233,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double Variance 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> /// <summary>
@ -216,48 +257,15 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double Skewness 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)); } get { return (Math.Sqrt(_population - 1.0)*(_population - (2*_draws))*(_population - (2*_success)))/(Math.Sqrt(_draws*_success*(_population - _success)*(_population - _draws))*(_population - 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);
}
#endregion
#region IDiscreteDistribution Members
/// <summary> /// <summary>
/// Gets the mode of the distribution. /// Gets the mode of the distribution.
/// </summary> /// </summary>
public int Mode public int Mode
{ {
get { return (_n + 1) * (_m + 1) / (_populationSize + 2); } get { return (_draws + 1)*(_success + 1)/(_population + 2); }
} }
/// <summary> /// <summary>
@ -273,7 +281,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public int Minimum public int Minimum
{ {
get { return Math.Max(0, _n + _m - _populationSize); } get { return Math.Max(0, _draws + _success - _population); }
} }
/// <summary> /// <summary>
@ -281,11 +289,11 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public int Maximum public int Maximum
{ {
get { return Math.Min(_m, _n); } get { return Math.Min(_success, _draws); }
} }
/// <summary> /// <summary>
/// Computes values of the probability mass function. /// Computes values of the probability mass function (PMF), i.e. P(X = x).
/// </summary> /// </summary>
/// <param name="k">The location in the domain where we want to evaluate the probability mass function.</param> /// <param name="k">The location in the domain where we want to evaluate the probability mass function.</param>
/// <returns> /// <returns>
@ -293,11 +301,11 @@ namespace MathNet.Numerics.Distributions
/// </returns> /// </returns>
public double Probability(int k) 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> /// <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> /// </summary>
/// <param name="k">The location in the domain where we want to evaluate the log probability mass function.</param> /// <param name="k">The location in the domain where we want to evaluate the log probability mass function.</param>
/// <returns> /// <returns>
@ -308,34 +316,57 @@ namespace MathNet.Numerics.Distributions
return Math.Log(Probability(k)); 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> /// <summary>
/// Generates a sample from the Hypergeometric distribution without doing parameter checking. /// Generates a sample from the Hypergeometric distribution without doing parameter checking.
/// </summary> /// </summary>
/// <param name="rnd">The random number generator to use.</param> /// <param name="rnd">The random number generator to use.</param>
/// <param name="size">The Total parameter of the distribution.</param> /// <param name="population">The size of the population (N).</param>
/// <param name="m">The m parameter of the distribution.</param> /// <param name="success">The number successes within the population (K, M).</param>
/// <param name="n">The n parameter of the distribution.</param> /// <param name="draws">The n parameter of the distribution.</param>
/// <returns>a random number from the Hypergeometric distribution.</returns> /// <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; var x = 0;
do do
{ {
var p = (double)m / size; var p = (double) success/population;
var r = rnd.NextDouble(); var r = rnd.NextDouble();
if (r < p) if (r < p)
{ {
x++; x++;
m--; success--;
} }
size--; population--;
n--; draws--;
} } while (0 < draws);
while (0 < n);
return x; return x;
} }
@ -346,7 +377,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>The number of successes in n trials.</returns> /// <returns>The number of successes in n trials.</returns>
public int Sample() public int Sample()
{ {
return SampleUnchecked(RandomSource, _populationSize, _m, _n); return SampleUnchecked(RandomSource, _population, _success, _draws);
} }
/// <summary> /// <summary>
@ -357,7 +388,7 @@ namespace MathNet.Numerics.Distributions
{ {
while (true) 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. /// Samples a random variable.
/// </summary> /// </summary>
/// <param name="rnd">The random number generator to use.</param> /// <param name="rnd">The random number generator to use.</param>
/// <param name="populationSize">The population size.</param> /// <param name="population">The size of the population (N).</param>
/// <param name="m">The m parameter of the distribution.</param> /// <param name="success">The number successes within the population (K, M).</param>
/// <param name="n">The n parameter of the distribution.</param> /// <param name="draws">The number of draws without replacement (n).</param>
public static int Sample(Random rnd, int populationSize, int m, int n) 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); throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
} }
return SampleUnchecked(rnd, populationSize, m, n); return SampleUnchecked(rnd, population, success, draws);
} }
/// <summary> /// <summary>
/// Samples a sequence of this random variable. /// Samples a sequence of this random variable.
/// </summary> /// </summary>
/// <param name="rnd">The random number generator to use.</param> /// <param name="rnd">The random number generator to use.</param>
/// <param name="populationSize">The population size.</param> /// <param name="population">The size of the population (N).</param>
/// <param name="m">The m parameter of the distribution.</param> /// <param name="success">The number successes within the population (K, M).</param>
/// <param name="n">The n parameter of the distribution.</param> /// <param name="draws">The number of draws without replacement (n).</param>
public static IEnumerable<int> Samples(Random rnd, int populationSize, int m, int n) 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); throw new ArgumentOutOfRangeException(Resources.InvalidDistributionParameters);
} }
while (true) while (true)
{ {
yield return SampleUnchecked(rnd, populationSize, m, n); yield return SampleUnchecked(rnd, population, success, draws);
} }
} }
} }

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

@ -64,7 +64,6 @@ namespace MathNet.Numerics.Distributions
public double R public double R
{ {
get { return _r; } get { return _r; }
set { SetParameters(value, _p); } set { SetParameters(value, _p); }
} }
@ -74,7 +73,6 @@ namespace MathNet.Numerics.Distributions
public double P public double P
{ {
get { return _p; } get { return _p; }
set { SetParameters(_r, value); } set { SetParameters(_r, value); }
} }
@ -85,8 +83,20 @@ namespace MathNet.Numerics.Distributions
/// <param name="p">The probability of a trial resulting in success.</param> /// <param name="p">The probability of a trial resulting in success.</param>
public NegativeBinomial(double r, double p) 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); SetParameters(r, p);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -146,7 +156,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)
@ -297,8 +306,7 @@ namespace MathNet.Numerics.Distributions
{ {
k = k + 1; k = k + 1;
p1 = p1*rnd.NextDouble(); p1 = p1*rnd.NextDouble();
} } while (p1 >= c);
while (p1 >= c);
return k - 1; return k - 1;
} }

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

@ -56,7 +56,6 @@ namespace MathNet.Numerics.Distributions
public double Lambda public double Lambda
{ {
get { return _lambda; } get { return _lambda; }
set { SetParameters(value); } 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> /// <exception cref="System.ArgumentOutOfRangeException">If <paramref name="lambda"/> is equal or less then 0.0.</exception>
public Poisson(double lambda) 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); SetParameters(lambda);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -115,7 +126,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -62,16 +62,24 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Zipf"/> class. /// Initializes a new instance of the <see cref="Zipf"/> class.
/// </summary> /// </summary>
/// <param name="s"> /// <param name="s">The s parameter of the distribution.</param>
/// The s parameter of the distribution. /// <param name="n">The n parameter of the distribution.</param>
/// </param>
/// <param name="n">
/// The n parameter of the distribution.
/// </param>
public Zipf(double s, int n) 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); SetParameters(s, n);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -112,7 +120,6 @@ namespace MathNet.Numerics.Distributions
public double S public double S
{ {
get { return _s; } get { return _s; }
set { SetParameters(value, _n); } set { SetParameters(value, _n); }
} }
@ -122,7 +129,6 @@ namespace MathNet.Numerics.Distributions
public int N public int N
{ {
get { return _n; } get { return _n; }
set { SetParameters(_s, value); } set { SetParameters(_s, value); }
} }
@ -143,7 +149,6 @@ namespace MathNet.Numerics.Distributions
public Random RandomSource public Random RandomSource
{ {
get { return _random; } get { return _random; }
set set
{ {
if (value == null) if (value == null)

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

@ -48,12 +48,12 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// The Dirichlet distribution parameters. /// The Dirichlet distribution parameters.
/// </summary> /// </summary>
private double[] _alpha; double[] _alpha;
/// <summary> /// <summary>
/// The distribution's random number generator. /// The distribution's random number generator.
/// </summary> /// </summary>
private Random _random; Random _random;
/// <summary> /// <summary>
/// Initializes a new instance of the Dirichlet class. The distribution will /// 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> /// <param name="alpha">An array with the Dirichlet parameters.</param>
public Dirichlet(double[] alpha) public Dirichlet(double[] alpha)
{ {
_random = new Random();
SetParameters(alpha); SetParameters(alpha);
RandomSource = new Random();
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Dirichlet"/> class. /// Initializes a new instance of the Dirichlet class. The distribution will
/// <seealso cref="System.Random"/> /// be initialized with the default <seealso cref="System.Random"/> random number generator.
/// random number generator.
/// </summary> /// </summary>
/// <param name="alpha"> /// <param name="alpha">An array with the Dirichlet parameters.</param>
/// The value of each parameter of the Dirichlet distribution. /// <param name="randomSource">The random number generator which is used to draw random samples.</param>
/// </param> public Dirichlet(double[] alpha, Random randomSource)
/// <param name="k"> {
/// The dimension of the Dirichlet distribution. _random = randomSource ?? new Random();
/// </param> 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) public Dirichlet(double alpha, int k)
{ {
// Create a parameter structure. // Create a parameter structure.
@ -86,8 +92,27 @@ namespace MathNet.Numerics.Distributions
parm[i] = alpha; 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); SetParameters(parm);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -124,7 +149,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
/// <param name="alpha">The parameters of the Dirichlet distribution.</param> /// <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> /// <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)) if (Control.CheckDistributionParameters && !IsValidParameterSet(alpha))
{ {
@ -150,10 +175,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public int Dimension public int Dimension
{ {
get get { return _alpha.Length; }
{
return _alpha.Length;
}
} }
/// <summary> /// <summary>
@ -161,26 +183,16 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double[] Alpha public double[] Alpha
{ {
get get { return _alpha; }
{ set { SetParameters(value); }
return _alpha;
}
set
{
SetParameters(value);
}
} }
/// <summary> /// <summary>
/// Gets the sum of the Dirichlet parameters. /// Gets the sum of the Dirichlet parameters.
/// </summary> /// </summary>
private double AlphaSum double AlphaSum
{
get
{ {
return _alpha.Sum(); get { return _alpha.Sum(); }
}
} }
/// <summary> /// <summary>
@ -301,11 +313,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public Random RandomSource public Random RandomSource
{ {
get get { return _random; }
{
return _random;
}
set set
{ {
if (value == null) if (value == null)

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

@ -47,36 +47,44 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// The degrees of freedom for the inverse Wishart distribution. /// The degrees of freedom for the inverse Wishart distribution.
/// </summary> /// </summary>
private double _nu; double _nu;
/// <summary> /// <summary>
/// The scale matrix for the inverse Wishart distribution. /// The scale matrix for the inverse Wishart distribution.
/// </summary> /// </summary>
private Matrix<double> _s; Matrix<double> _s;
/// <summary> /// <summary>
/// Caches the Cholesky factorization of the scale matrix. /// Caches the Cholesky factorization of the scale matrix.
/// </summary> /// </summary>
private Cholesky<double> _chol; Cholesky<double> _chol;
/// <summary> /// <summary>
/// The distribution's random number generator. /// The distribution's random number generator.
/// </summary> /// </summary>
private Random _random; Random _random;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="InverseWishart"/> class. /// Initializes a new instance of the <see cref="InverseWishart"/> class.
/// </summary> /// </summary>
/// <param name="nu"> /// <param name="nu">The degrees of freedom for the inverse Wishart distribution.</param>
/// The degrees of freedom for the inverse Wishart distribution. /// <param name="s">The scale matrix for the inverse Wishart distribution.</param>
/// </param>
/// <param name="s">
/// The scale matrix for the inverse Wishart distribution.
/// </param>
public InverseWishart(double nu, Matrix<double> s) 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); SetParameters(nu, s);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -94,7 +102,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="nu">The degrees of freedom 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> /// <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> /// <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)) 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="nu">The degrees of freedom for the Wishart distribution.</param>
/// <param name="s">The scale matrix 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> /// <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) if (s.RowCount != s.ColumnCount)
{ {
@ -140,15 +148,8 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double Nu public double Nu
{ {
get get { return _nu; }
{ set { SetParameters(value, _s); }
return _nu;
}
set
{
SetParameters(value, _s);
}
} }
/// <summary> /// <summary>
@ -156,15 +157,8 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public Matrix<double> S public Matrix<double> S
{ {
get get { return _s; }
{ set { SetParameters(_nu, value); }
return _s;
}
set
{
SetParameters(_nu, value);
}
} }
/// <summary> /// <summary>
@ -172,11 +166,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public Random RandomSource public Random RandomSource
{ {
get get { return _random; }
{
return _random;
}
set set
{ {
if (value == null) if (value == null)
@ -194,10 +184,7 @@ namespace MathNet.Numerics.Distributions
/// <value>The mean of the distribution.</value> /// <value>The mean of the distribution.</value>
public Matrix<double> Mean public Matrix<double> Mean
{ {
get get { return _s*(1.0/(_nu - _s.RowCount - 1.0)); }
{
return _s * (1.0 / (_nu - _s.RowCount - 1.0));
}
} }
/// <summary> /// <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> /// <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 public Matrix<double> Mode
{ {
get get { return _s*(1.0/(_nu + _s.RowCount + 1.0)); }
{
return _s * (1.0 / (_nu + _s.RowCount + 1.0));
}
} }
/// <summary> /// <summary>

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

@ -48,42 +48,48 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// The mean of the matrix normal distribution. /// The mean of the matrix normal distribution.
/// </summary> /// </summary>
private Matrix<double> _m; Matrix<double> _m;
/// <summary> /// <summary>
/// The covariance matrix for the rows. /// The covariance matrix for the rows.
/// </summary> /// </summary>
private Matrix<double> _v; Matrix<double> _v;
/// <summary> /// <summary>
/// The covariance matrix for the columns. /// The covariance matrix for the columns.
/// </summary> /// </summary>
private Matrix<double> _k; Matrix<double> _k;
/// <summary> /// <summary>
/// The distribution's random number generator. /// The distribution's random number generator.
/// </summary> /// </summary>
private Random _random; Random _random;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MatrixNormal"/> class. /// Initializes a new instance of the <see cref="MatrixNormal"/> class.
/// </summary> /// </summary>
/// <param name="m"> /// <param name="m">The mean of the matrix normal.</param>
/// The mean of the matrix normal. /// <param name="v">The covariance matrix for the rows.</param>
/// </param> /// <param name="k">The covariance matrix for the columns.</param>
/// <param name="v"> /// <exception cref="ArgumentOutOfRangeException">If the dimensions of the mean and two covariance matrices don't match.</exception>
/// 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) 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); SetParameters(m, v, k);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -103,15 +109,8 @@ namespace MathNet.Numerics.Distributions
/// <value>The mean of the distribution.</value> /// <value>The mean of the distribution.</value>
public Matrix<double> Mean public Matrix<double> Mean
{ {
get get { return _m; }
{ set { SetParameters(value, _v, _k); }
return _m;
}
set
{
SetParameters(value, _v, _k);
}
} }
/// <summary> /// <summary>
@ -120,15 +119,8 @@ namespace MathNet.Numerics.Distributions
/// <value>The row covariance.</value> /// <value>The row covariance.</value>
public Matrix<double> RowCovariance public Matrix<double> RowCovariance
{ {
get get { return _v; }
{ set { SetParameters(_m, value, _k); }
return _v;
}
set
{
SetParameters(_m, value, _k);
}
} }
/// <summary> /// <summary>
@ -137,15 +129,8 @@ namespace MathNet.Numerics.Distributions
/// <value>The column covariance.</value> /// <value>The column covariance.</value>
public Matrix<double> ColumnCovariance public Matrix<double> ColumnCovariance
{ {
get get { return _k; }
{ set { SetParameters(_m, _v, value); }
return _k;
}
set
{
SetParameters(_m, _v, value);
}
} }
/// <summary> /// <summary>
@ -155,7 +140,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="v">The covariance matrix for the rows.</param> /// <param name="v">The covariance matrix for the rows.</param>
/// <param name="k">The covariance matrix for the columns.</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> /// <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)) 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="v">The covariance matrix for the rows.</param>
/// <param name="k">The covariance matrix for the columns.</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> /// <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 n = m.RowCount;
var p = m.ColumnCount; var p = m.ColumnCount;
@ -212,11 +197,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public Random RandomSource public Random RandomSource
{ {
get get { return _random; }
{
return _random;
}
set set
{ {
if (value == null) if (value == null)
@ -305,7 +286,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="mean">The mean of the vector normal distribution.</param> /// <param name="mean">The mean of the vector normal distribution.</param>
/// <param name="covariance">The covariance matrix 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> /// <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); var chol = Cholesky<double>.Create(covariance);
return SampleVectorNormal(rnd, mean, chol); 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="mean">The mean of the vector normal distribution.</param>
/// <param name="cholesky">The Cholesky factorization of the covariance matrix.</param> /// <param name="cholesky">The Cholesky factorization of the covariance matrix.</param>
/// <returns>a sequence of samples from defined distribution.</returns> /// <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; var count = mean.Count;

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

@ -51,17 +51,17 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// Stores the normalized multinomial probabilities. /// Stores the normalized multinomial probabilities.
/// </summary> /// </summary>
private double[] _p; double[] _p;
/// <summary> /// <summary>
/// The number of trials. /// The number of trials.
/// </summary> /// </summary>
private int _n; int _n;
/// <summary> /// <summary>
/// The distribution's random number generator. /// The distribution's random number generator.
/// </summary> /// </summary>
private Random _random; Random _random;
/// <summary> /// <summary>
/// Initializes a new instance of the Multinomial class. /// 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> /// <exception cref="ArgumentOutOfRangeException">If <paramref name="n"/> is negative.</exception>
public Multinomial(double[] p, int n) 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); SetParameters(p, n);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -122,7 +137,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="n">The number of trials.</param> /// <param name="n">The number of trials.</param>
/// <returns>If any of the probabilities are negative returns <c>false</c>, /// <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> /// 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; var sum = 0.0;
foreach (var t in p) foreach (var t in p)
@ -150,7 +165,7 @@ namespace MathNet.Numerics.Distributions
/// as this is often impossible using floating point arithmetic.</param> /// as this is often impossible using floating point arithmetic.</param>
/// <param name="n">The number of trials.</param> /// <param name="n">The number of trials.</param>
/// <exception cref="ArgumentOutOfRangeException">When the parameters don't pass the <see cref="IsValidParameterSet"/> function.</exception> /// <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)) if (Control.CheckDistributionParameters && !IsValidParameterSet(p, n))
{ {
@ -166,15 +181,8 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double[] P public double[] P
{ {
get get { return (double[]) _p.Clone(); }
{ set { SetParameters(value, _n); }
return (double[])_p.Clone();
}
set
{
SetParameters(value, _n);
}
} }
/// <summary> /// <summary>
@ -182,15 +190,8 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public int N public int N
{ {
get get { return _n; }
{ set { SetParameters(_p, value); }
return _n;
}
set
{
SetParameters(_p, value);
}
} }
/// <summary> /// <summary>
@ -198,11 +199,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public Random RandomSource public Random RandomSource
{ {
get get { return _random; }
{
return _random;
}
set set
{ {
if (value == null) if (value == null)
@ -219,10 +216,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public Vector<double> Mean public Vector<double> Mean
{ {
get get { return _n*(DenseVector) P; }
{
return _n * (DenseVector)P;
}
} }
/// <summary> /// <summary>

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

@ -39,22 +39,18 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// The mean value. /// The mean value.
/// </summary> /// </summary>
private double _mean; double _mean;
/// <summary> /// <summary>
/// The precision value. /// The precision value.
/// </summary> /// </summary>
private double _precision; double _precision;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MeanPrecisionPair"/> struct. /// Initializes a new instance of the <see cref="MeanPrecisionPair"/> struct.
/// </summary> /// </summary>
/// <param name="m"> /// <param name="m">The mean of the pair.</param>
/// The mean of the pair. /// <param name="p">The precision of the pair.</param>
/// </param>
/// <param name="p">
/// The precision of the pair.
/// </param>
public MeanPrecisionPair(double m, double p) public MeanPrecisionPair(double m, double p)
{ {
_mean = m; _mean = m;
@ -66,15 +62,9 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double Mean public double Mean
{ {
get get { return _mean; }
{
return _mean;
}
set set { _mean = value; }
{
_mean = value;
}
} }
/// <summary> /// <summary>
@ -82,15 +72,9 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double Precision public double Precision
{ {
get get { return _precision; }
{
return _precision;
}
set set { _precision = value; }
{
_precision = value;
}
} }
} }
@ -116,47 +100,53 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// The location of the mean. /// The location of the mean.
/// </summary> /// </summary>
private double _meanLocation; double _meanLocation;
/// <summary> /// <summary>
/// The scale of the mean. /// The scale of the mean.
/// </summary> /// </summary>
private double _meanScale; double _meanScale;
/// <summary> /// <summary>
/// The shape of the precision. /// The shape of the precision.
/// </summary> /// </summary>
private double _precisionShape; double _precisionShape;
/// <summary> /// <summary>
/// The inverse scale of the precision. /// The inverse scale of the precision.
/// </summary> /// </summary>
private double _precisionInvScale; double _precisionInvScale;
/// <summary> /// <summary>
/// The distribution's random number generator. /// The distribution's random number generator.
/// </summary> /// </summary>
private Random _random; Random _random;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="NormalGamma"/> class. /// Initializes a new instance of the <see cref="NormalGamma"/> class.
/// </summary> /// </summary>
/// <param name="meanLocation"> /// <param name="meanLocation">The location of the mean.</param>
/// The location of the mean. /// <param name="meanScale">The scale of the mean.</param>
/// </param> /// <param name="precisionShape">The shape of the precision.</param>
/// <param name="meanScale"> /// <param name="precisionInverseScale">The inverse scale of the precision.</param>
/// 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) public NormalGamma(double meanLocation, double meanScale, double precisionShape, double precisionInverseScale)
{ {
SetParameters(meanLocation, meanScale, precisionShape, precisionInverseScale);
_random = new Random(); _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> /// <summary>
@ -167,7 +157,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="precShape">The shape of the precision.</param> /// <param name="precShape">The shape of the precision.</param>
/// <param name="precInvScale">The inverse scale 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> /// <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 if (meanScale <= 0.0 || precShape <= 0.0 || precInvScale <= 0.0
|| Double.IsNaN(meanLocation) || Double.IsNaN(meanScale) || Double.IsNaN(precShape) || 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="precShape">The shape of the precision.</param>
/// <param name="precInvScale">The inverse scale 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> /// <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)) if (Control.CheckDistributionParameters && !IsValidParameterSet(meanLocation, meanScale, precShape, precInvScale))
{ {
@ -215,15 +205,8 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double MeanLocation public double MeanLocation
{ {
get get { return _meanLocation; }
{ set { SetParameters(value, _meanScale, _precisionShape, _precisionInvScale); }
return _meanLocation;
}
set
{
SetParameters(value, _meanScale, _precisionShape, _precisionInvScale);
}
} }
/// <summary> /// <summary>
@ -231,15 +214,8 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double MeanScale public double MeanScale
{ {
get get { return _meanScale; }
{ set { SetParameters(_meanLocation, value, _precisionShape, _precisionInvScale); }
return _meanScale;
}
set
{
SetParameters(_meanLocation, value, _precisionShape, _precisionInvScale);
}
} }
/// <summary> /// <summary>
@ -247,15 +223,8 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double PrecisionShape public double PrecisionShape
{ {
get get { return _precisionShape; }
{ set { SetParameters(_meanLocation, _meanScale, value, _precisionInvScale); }
return _precisionShape;
}
set
{
SetParameters(_meanLocation, _meanScale, value, _precisionInvScale);
}
} }
/// <summary> /// <summary>
@ -263,15 +232,8 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double PrecisionInverseScale public double PrecisionInverseScale
{ {
get get { return _precisionInvScale; }
{ set { SetParameters(_meanLocation, _meanScale, _precisionShape, value); }
return _precisionInvScale;
}
set
{
SetParameters(_meanLocation, _meanScale, _precisionShape, value);
}
} }
/// <summary> /// <summary>
@ -279,11 +241,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public Random RandomSource public Random RandomSource
{ {
get get { return _random; }
{
return _random;
}
set set
{ {
if (value == null) if (value == null)
@ -324,10 +282,7 @@ namespace MathNet.Numerics.Distributions
/// <value>The mean of the distribution.</value> /// <value>The mean of the distribution.</value>
public MeanPrecisionPair Mean public MeanPrecisionPair Mean
{ {
get get { return Double.IsPositiveInfinity(_precisionInvScale) ? new MeanPrecisionPair(_meanLocation, _precisionShape) : new MeanPrecisionPair(_meanLocation, _precisionShape/_precisionInvScale); }
{
return Double.IsPositiveInfinity(_precisionInvScale) ? new MeanPrecisionPair(_meanLocation, _precisionShape) : new MeanPrecisionPair(_meanLocation, _precisionShape / _precisionInvScale);
}
} }
/// <summary> /// <summary>
@ -336,10 +291,7 @@ namespace MathNet.Numerics.Distributions
/// <value>The mean of the distribution.</value> /// <value>The mean of the distribution.</value>
public MeanPrecisionPair Variance public MeanPrecisionPair Variance
{ {
get get { return new MeanPrecisionPair(_precisionInvScale/(_meanScale*(_precisionShape - 1)), _precisionShape/Math.Sqrt(_precisionInvScale)); }
{
return new MeanPrecisionPair(_precisionInvScale / (_meanScale * (_precisionShape - 1)), _precisionShape / Math.Sqrt(_precisionInvScale));
}
} }
/// <summary> /// <summary>

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

@ -49,36 +49,44 @@ namespace MathNet.Numerics.Distributions
/// <summary> /// <summary>
/// The degrees of freedom for the Wishart distribution. /// The degrees of freedom for the Wishart distribution.
/// </summary> /// </summary>
private double _nu; double _nu;
/// <summary> /// <summary>
/// The scale matrix for the Wishart distribution. /// The scale matrix for the Wishart distribution.
/// </summary> /// </summary>
private Matrix<double> _s; Matrix<double> _s;
/// <summary> /// <summary>
/// Caches the Cholesky factorization of the scale matrix. /// Caches the Cholesky factorization of the scale matrix.
/// </summary> /// </summary>
private Cholesky<double> _chol; Cholesky<double> _chol;
/// <summary> /// <summary>
/// The distribution's random number generator. /// The distribution's random number generator.
/// </summary> /// </summary>
private Random _random; Random _random;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Wishart"/> class. /// Initializes a new instance of the <see cref="Wishart"/> class.
/// </summary> /// </summary>
/// <param name="nu"> /// <param name="nu">The degrees of freedom for the Wishart distribution.</param>
/// The degrees of freedom for the Wishart distribution. /// <param name="s">The scale matrix for the Wishart distribution.</param>
/// </param>
/// <param name="s">
/// The scale matrix for the Wishart distribution.
/// </param>
public Wishart(double nu, Matrix<double> s) 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); SetParameters(nu, s);
RandomSource = new Random();
} }
/// <summary> /// <summary>
@ -87,7 +95,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="nu">The degrees of freedom 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> /// <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> /// <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)) 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="nu">The degrees of freedom for the Wishart distribution.</param>
/// <param name="s">The scale matrix 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> /// <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) if (s.RowCount != s.ColumnCount)
{ {
@ -133,15 +141,8 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public double Nu public double Nu
{ {
get get { return _nu; }
{ set { SetParameters(value, _s); }
return _nu;
}
set
{
SetParameters(value, _s);
}
} }
/// <summary> /// <summary>
@ -149,15 +150,8 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public Matrix<double> S public Matrix<double> S
{ {
get get { return _s; }
{ set { SetParameters(_nu, value); }
return _s;
}
set
{
SetParameters(_nu, value);
}
} }
/// <summary> /// <summary>
@ -174,11 +168,7 @@ namespace MathNet.Numerics.Distributions
/// </summary> /// </summary>
public Random RandomSource public Random RandomSource
{ {
get get { return _random; }
{
return _random;
}
set set
{ {
if (value == null) if (value == null)
@ -196,10 +186,7 @@ namespace MathNet.Numerics.Distributions
/// <value>The mean of the distribution.</value> /// <value>The mean of the distribution.</value>
public Matrix<double> Mean public Matrix<double> Mean
{ {
get get { return _nu*_s; }
{
return _nu * _s;
}
} }
/// <summary> /// <summary>
@ -208,10 +195,7 @@ namespace MathNet.Numerics.Distributions
/// <value>The mode of the distribution.</value> /// <value>The mode of the distribution.</value>
public Matrix<double> Mode public Matrix<double> Mode
{ {
get get { return (_nu - _s.RowCount - 1.0)*_s; }
{
return (_nu - _s.RowCount - 1.0) * _s;
}
} }
/// <summary> /// <summary>
@ -307,7 +291,7 @@ namespace MathNet.Numerics.Distributions
/// <param name="s">The S parameter to use.</param> /// <param name="s">The S parameter to use.</param>
/// <param name="chol">The cholesky decomposition to use.</param> /// <param name="chol">The cholesky decomposition to use.</param>
/// <returns>a random number from the distribution.</returns> /// <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; var count = s.RowCount;

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. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using MathNet.Numerics.Threading;
namespace MathNet.Numerics.LinearAlgebra.Complex namespace MathNet.Numerics.LinearAlgebra.Complex
{ {
using Algorithms.LinearAlgebra; 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> /// <summary>
/// Pointwise multiplies this matrix with 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> /// </summary>
@ -611,16 +631,16 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary> /// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary> /// </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> /// <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; var denseResult = result as DenseMatrix;
if (denseOther == null || denseResult == null) if (denseOther == null || denseResult == null)
{ {
base.DoPointwiseDivide(other, result); base.DoPointwiseDivide(divisor, result);
} }
else 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> /// <summary>
/// Adds another matrix to this matrix. /// Adds another matrix to this matrix.
/// </summary> /// </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> /// <summary>
/// Subtracts another matrix from this matrix. /// Subtracts another matrix from this matrix.
/// </summary> /// </summary>

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

@ -434,14 +434,33 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary> /// <summary>
/// Computes the dot product between this vector and another vector. /// Computes the dot product between this vector and another vector.
/// </summary> /// </summary>
/// <param name="other">The other vector to add.</param> /// <param name="other">The other vector.</param>
/// <returns>s /// <returns>The sum of a[i]*b[i] for all i.</returns>
/// The result of the addition.</returns>
protected override Complex DoDotProduct(Vector<Complex> other) protected override Complex DoDotProduct(Vector<Complex> other)
{ {
var denseVector = other as DenseVector; 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> /// <summary>
@ -580,31 +599,67 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override Complex Sum() public override Complex Sum()
{ {
var sum = Complex.Zero; var sum = Complex.Zero;
for (var i = 0; i < _length; i++) for (var i = 0; i < _length; i++)
{ {
sum += _values[i]; sum += _values[i];
} }
return sum; return sum;
} }
/// <summary> /// <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> /// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns> /// <returns>The sum of the absolute values.</returns>
public override Complex SumMagnitudes() public override Complex L1Norm()
{ {
var sum = Complex.Zero; var sum = Complex.Zero;
for (var i = 0; i < _length; i++) for (var i = 0; i < _length; i++)
{ {
sum += _values[i].Magnitude; sum += _values[i].Magnitude;
} }
return sum; 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> /// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector. /// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary> /// </summary>
@ -628,17 +683,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary> /// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector. /// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <param name="result">The vector to store the result of the pointwise division.</param>
/// <remarks></remarks> /// <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; var denseResult = result as DenseVector;
if (denseOther == null || denseResult == null) if (denseOther == null || denseResult == null)
{ {
base.DoPointwiseDivide(other, result); base.DoPointwiseDivide(divisor, result);
} }
else else
{ {
@ -693,43 +748,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return OuterProduct(this, v); 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 #region Parse Functions
/// <summary> /// <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++) 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) if (norm == 0.0)
{ {
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient); throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);

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

@ -129,6 +129,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return norm; 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> /// <summary>
/// Adds another matrix to this matrix. /// Adds another matrix to this matrix.
/// </summary> /// </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> /// <summary>
/// Subtracts another matrix from this matrix. /// Subtracts another matrix from this matrix.
/// </summary> /// </summary>
@ -225,11 +257,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary> /// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix. /// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary> /// </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> /// <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> /// <summary>
@ -344,27 +392,47 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary> /// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary> /// </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> /// <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 j = 0; j < ColumnCount; j++)
{ {
for (var i = 0; i < RowCount; i++) 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> /// <summary>
/// Computes the modulus for each element of the matrix. /// Computes the modulus for each element of the matrix.
/// </summary> /// </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> /// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(Complex divisor, Matrix<Complex> result) 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> /// <summary>

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

@ -39,6 +39,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex; using Complex = Numerics.Complex;
#else #else
using Complex = System.Numerics.Complex; using Complex = System.Numerics.Complex;
#endif #endif
/// <summary> /// <summary>
@ -76,23 +77,23 @@ 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 /// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator. /// iterator.
/// </summary> /// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined(); static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary> /// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default /// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used. /// pre-conditioner will be used.
/// </summary> /// </summary>
private IPreConditioner _preconditioner; IPreConditioner _preconditioner;
/// <summary> /// <summary>
/// The iterative process controller. /// The iterative process controller.
/// </summary> /// </summary>
private IIterator _iterator; IIterator _iterator;
/// <summary> /// <summary>
/// Indicates if the user has stopped the solver. /// Indicates if the user has stopped the solver.
/// </summary> /// </summary>
private bool _hasBeenStopped; bool _hasBeenStopped;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class. /// Initializes a new instance of the <see cref="BiCgStab"/> class.
@ -101,7 +102,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// When using this constructor the solver will use the <see cref="IIterator"/> with /// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner. /// the standard settings and a default preconditioner.
/// </remarks> /// </remarks>
public BiCgStab() : this(null, null) public BiCgStab()
: this(null, null)
{ {
} }
@ -124,7 +126,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process. </param> /// <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. /// the standard settings.
/// </remarks> /// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param> /// <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> /// </summary>
public ICalculationStatus IterationResult public ICalculationStatus IterationResult
{ {
get get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
} }
/// <summary> /// <summary>
@ -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) // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
var oldRho = currentRho; var oldRho = currentRho;
currentRho = tempResiduals.DotProduct(residuals); currentRho = tempResiduals.ConjugateDotProduct(residuals);
// if (rho_(i-1) == 0) // METHOD FAILS // if (rho_(i-1) == 0) // METHOD FAILS
// If rho is only 1 ULP from zero then we fail. // If rho is only 1 ULP from zero then we fail.
@ -349,7 +350,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(vecPdash, nu); matrix.Multiply(vecPdash, nu);
// alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i) // 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 // s = r_(i-1) - alpha_i nu_i
nu.Multiply(-alpha, temp); nu.Multiply(-alpha, temp);
@ -393,7 +394,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(vecSdash, temp); matrix.Multiply(vecSdash, temp);
// omega_i = temp^T s / temp^T 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^ // x_i = x_(i-1) + alpha_i p^ + omega_i s^
temp.Multiply(-omega, residuals); temp.Multiply(-omega, residuals);
@ -437,7 +438,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="residual">Residual values in <see cref="Vector"/>.</param> /// <param name="residual">Residual values in <see cref="Vector"/>.</param>
/// <param name="x">Instance of the <see cref="Vector"/> x.</param> /// <param name="x">Instance of the <see cref="Vector"/> x.</param>
/// <param name="b">Instance of the <see cref="Vector"/> b.</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 // -Ax = residual
matrix.Multiply(x, residual); matrix.Multiply(x, residual);
@ -457,7 +458,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="source">Source <see cref="Vector"/>.</param> /// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param> /// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns> /// <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) if (_hasBeenStopped)
{ {

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

@ -39,6 +39,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex; using Complex = Numerics.Complex;
#else #else
using Complex = System.Numerics.Complex; using Complex = System.Numerics.Complex;
#endif #endif
/// <summary> /// <summary>
@ -377,7 +378,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(temp, s); matrix.Multiply(temp, s);
// alpha_k = (r*_0 * r_k) / (r*_0 * s_k) // 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 // y_k = t_(k-1) - r_k - alpha_k * w_(k-1) + alpha_k s_k
s.Subtract(w, temp); s.Subtract(w, temp);
@ -399,7 +400,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
// c_k = A d_k // c_k = A d_k
matrix.Multiply(temp, c); 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 // 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 // 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 // to do at least one at the start to initialize the
// system, but we'll only have to take special measures // system, but we'll only have to take special measures
// if we don't do any so ... // if we don't do any so ...
var ctdot = c.DotProduct(t); var ctdot = c.ConjugateDotProduct(t);
Complex eta; Complex eta;
Complex sigma; Complex sigma;
if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber)) if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber))
@ -427,7 +428,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
} }
else else
{ {
var ydot = y.DotProduct(y); var ydot = y.ConjugateDotProduct(y);
// yDot can only be zero if y is a zero vector // 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 // 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; ydot = 1.0;
} }
var ytdot = y.DotProduct(t); var ytdot = y.ConjugateDotProduct(t);
var cydot = c.DotProduct(y); var cydot = c.ConjugateDotProduct(y);
var denom = (cdot*ydot) - (cydot*cydot); 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) // 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. // 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 // w_k = c_k + beta_k s_k
s.Multiply(beta, temp2); s.Multiply(beta, temp2);

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

@ -43,6 +43,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex; using Complex = Numerics.Complex;
#else #else
using Complex = System.Numerics.Complex; using Complex = System.Numerics.Complex;
#endif #endif
/// <summary> /// <summary>
@ -73,39 +74,39 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <summary> /// <summary>
/// The default number of starting vectors. /// The default number of starting vectors.
/// </summary> /// </summary>
private const int DefaultNumberOfStartingVectors = 50; const int DefaultNumberOfStartingVectors = 50;
/// <summary> /// <summary>
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no /// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator. /// iterator.
/// </summary> /// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined(); static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary> /// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default /// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used. /// pre-conditioner will be used.
/// </summary> /// </summary>
private IPreConditioner _preconditioner; IPreConditioner _preconditioner;
/// <summary> /// <summary>
/// The iterative process controller. /// The iterative process controller.
/// </summary> /// </summary>
private IIterator _iterator; IIterator _iterator;
/// <summary> /// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space. /// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary> /// </summary>
private IList<Vector> _startingVectors; IList<Vector> _startingVectors;
/// <summary> /// <summary>
/// The number of starting vectors used by the algorithm /// The number of starting vectors used by the algorithm
/// </summary> /// </summary>
private int _numberOfStartingVectors = DefaultNumberOfStartingVectors; int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
/// <summary> /// <summary>
/// Indicates if the user has stopped the solver. /// Indicates if the user has stopped the solver.
/// </summary> /// </summary>
private bool _hasBeenStopped; bool _hasBeenStopped;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class. /// 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 /// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner. /// the standard settings and a default preconditioner.
/// </remarks> /// </remarks>
public MlkBiCgStab() : this(null, null) public MlkBiCgStab()
: this(null, null)
{ {
} }
@ -137,7 +139,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process.</param> /// <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. /// the standard settings.
/// </remarks> /// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param> /// <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 public int NumberOfStartingVectors
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return _numberOfStartingVectors; }
{
return _numberOfStartingVectors;
}
[DebuggerStepThrough] [DebuggerStepThrough]
set set
@ -236,10 +237,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
public IList<Vector> StartingVectors public IList<Vector> StartingVectors
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return _startingVectors; }
{
return _startingVectors;
}
[DebuggerStepThrough] [DebuggerStepThrough]
set set
@ -261,10 +259,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
public ICalculationStatus IterationResult public ICalculationStatus IterationResult
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
} }
/// <summary> /// <summary>
@ -420,14 +415,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
matrix.Multiply(gtemp, w[k - 1]); matrix.Multiply(gtemp, w[k - 1]);
// c_((j-1)k+k) = q^T_1 w_((j-1)k+k) // 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)) 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"); 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) // 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) // u_(jk+1) = r_((j-1)k+k) - alpha_(jk+1) w_((j-1)k+k)
w[k - 1].Multiply(-alpha, temp); 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 // rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2
matrix.Multiply(temp1, temp); 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 // If rho is zero then temp is a zero vector and we're probably
// about to have zero residuals (i.e. an exact solution). // 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 = 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) // r_(jk+1) = rho_(j+1) A u~_(jk+1) + u_(jk+1)
u.CopyTo(residuals); u.CopyTo(residuals);
@ -502,7 +497,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
for (var s = i; s < k - 1; s++) 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^(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) // z_d = z_d + beta^(jk+i)_((j-1)k+s) d_((j-1)k+s)
d[s].Multiply(beta, temp); d[s].Multiply(beta, temp);
@ -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)) // 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); zw.Multiply(rho, temp2);
residuals.Add(temp2, temp); 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) // z_g = z_g + beta^(jk+i)_((j-1)k+k) g_((j-1)k+k)
g[k - 1].Multiply(beta, temp); 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++) for (var s = 0; s < i - 1; s++)
{ {
// beta^(jk+i)_(jk+s) = -q^T_s+1 z_d / c_(jk+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) // z_d = z_d + beta^(jk+i)_(jk+s) * d_(jk+s)
d[s].Multiply(beta, temp); d[s].Multiply(beta, temp);
@ -573,14 +568,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
if (i < k - 1) if (i < k - 1)
{ {
// c_(jk+1) = q^T_i+1 d_(jk+i) // 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)) if (c[i].Real.AlmostEqual(0, 1) && c[i].Imaginary.AlmostEqual(0, 1))
{ {
throw new Exception("Iterative solver experience a numerical break down"); 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_(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) // u_(jk+i+1) = u_(jk+i) - alpha_(jk+i+1) d_(jk+i)
d[i].Multiply(-alpha, temp); d[i].Multiply(-alpha, temp);
@ -626,7 +621,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="maximumNumberOfStartingVectors">Maximum number</param> /// <param name="maximumNumberOfStartingVectors">Maximum number</param>
/// <param name="numberOfVariables">Number of variables</param> /// <param name="numberOfVariables">Number of variables</param>
/// <returns>Number of starting vectors to create</returns> /// <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 // Create no more starting vectors than the size of the problem - 1
return Math.Min(maximumNumberOfStartingVectors, (numberOfVariables - 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="numberOfVariables"/> is smaller than
/// the <paramref name="maximumNumberOfStartingVectors"/>. /// the <paramref name="maximumNumberOfStartingVectors"/>.
/// </returns> /// </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 // Create no more starting vectors than the size of the problem - 1
// Get random values and then orthogonalize them with // Get random values and then orthogonalize them with
@ -680,7 +675,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
result.Add((Vector) orthogonalMatrix.Column(i)); result.Add((Vector) orthogonalMatrix.Column(i));
// Normalize the result vector // 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; return result;
@ -692,7 +687,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
/// <param name="arraySize">Number of vectors</param> /// <param name="arraySize">Number of vectors</param>
/// <param name="vectorSize">Size of each vector</param> /// <param name="vectorSize">Size of each vector</param>
/// <returns>Array of random vectors</returns> /// <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]; var result = new Vector[arraySize];
for (var i = 0; i < result.Length; i++) 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="residual">Residual <see cref="Vector"/> data.</param>
/// <param name="x">x <see cref="Vector"/> data.</param> /// <param name="x">x <see cref="Vector"/> data.</param>
/// <param name="b">b <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 // -Ax = residual
matrix.Multiply(x, 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="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param> /// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns> /// <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) if (_hasBeenStopped)
{ {

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

@ -39,6 +39,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
using Complex = Numerics.Complex; using Complex = Numerics.Complex;
#else #else
using Complex = System.Numerics.Complex; using Complex = System.Numerics.Complex;
#endif #endif
/// <summary> /// <summary>
@ -282,15 +283,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
var temp1 = new DenseVector(input.Count); var temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count); var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.Norm(2);
// Define the scalars // Define the scalars
Complex alpha = 0; Complex alpha = 0;
Complex eta = 0; Complex eta = 0;
double theta = 0; double theta = 0;
var tau = startNorm.Real; // Initialize
var tau = input.L2Norm().Real;
Complex rho = tau*tau; Complex rho = tau*tau;
// Calculate the initial values for v // Calculate the initial values for v
@ -311,7 +310,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
if (IsEven(iterationNumber)) if (IsEven(iterationNumber))
{ {
// sigma = (v, r) // 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)) if (sigma.Real.AlmostEqual(0, 1) && sigma.Imaginary.AlmostEqual(0, 1))
{ {
// FAIL HERE // FAIL HERE
@ -349,7 +348,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
yinternal.Add(temp, d); yinternal.Add(temp, d);
// theta = ||pseudoResiduals||_2 / tau // theta = ||pseudoResiduals||_2 / tau
theta = pseudoResiduals.Norm(2).Real/tau; theta = pseudoResiduals.L2Norm().Real/tau;
var c = 1/Math.Sqrt(1 + (theta*theta)); var c = 1/Math.Sqrt(1 + (theta*theta));
// tau = tau * theta * c // tau = tau * theta * c
@ -392,7 +391,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Solvers.Iterative
break; break;
} }
var rhoNew = pseudoResiduals.DotProduct(r.Conjugate()); var rhoNew = r.ConjugateDotProduct(pseudoResiduals);
var beta = rhoNew/rho; var beta = rhoNew/rho;
// Update rho for the next loop // 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 // pivot the row
PivotRow(workVector); PivotRow(workVector);
var vectorNorm = workVector.Norm(Double.PositiveInfinity); var vectorNorm = workVector.InfinityNorm();
// for j = 1, .. , i - 1) // for j = 1, .. , i - 1)
for (var j = 0; j < i; j++) 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 // 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. // 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. // Check if we have NaN's. If so we've gone way beyond normal divergence.
// Stop the iteration. // 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 // Store the infinity norms of both the solution and residual vectors
var residualNorm = residualVector.Norm(Double.PositiveInfinity); var residualNorm = residualVector.InfinityNorm();
var solutionNorm = solutionVector.Norm(Double.PositiveInfinity); var solutionNorm = solutionVector.InfinityNorm();
if (Double.IsNaN(solutionNorm.Real) || Double.IsNaN(residualNorm.Real)) 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 // Store the infinity norms of both the solution and residual vectors
// These values will be used to calculate the relative drop in residuals // These values will be used to calculate the relative drop in residuals
// later on. // later on.
var residualNorm = residualVector.Norm(Double.PositiveInfinity); var residualNorm = residualVector.InfinityNorm();
// Check the residuals by calculating: // Check the residuals by calculating:
// ||r_i|| <= stop_tol * ||b|| // ||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. // First check that we have real numbers not NaN's.
// NaN's can occur when the iterative process diverges so we // 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> /// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary> /// </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> /// <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(); result.Clear();
@ -1073,7 +1073,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{ {
if (!values[j].IsZero()) 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> /// <summary>
/// Computes the dot product between this vector and another vector. /// Computes the dot product between this vector and another vector.
/// </summary> /// </summary>
/// <param name="other"> /// <param name="other">The other vector.</param>
/// The other vector to add. /// <returns>The sum of a[i]*b[i] for all i.</returns>
/// </param>
/// <returns>s
/// The result of the addition.
/// </returns>
protected override Complex DoDotProduct(Vector<Complex> other) protected override Complex DoDotProduct(Vector<Complex> other)
{ {
var result = Complex.Zero; var result = Complex.Zero;
if (ReferenceEquals(this, other)) if (ReferenceEquals(this, other))
{ {
for (var i = 0; i < _storage.ValueCount; i++) 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]); 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; return result;
} }
@ -744,25 +763,58 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{ {
result += _storage.Values[i]; result += _storage.Values[i];
} }
return result; return result;
} }
/// <summary> /// <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> /// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns> /// <returns>The sum of the absolute values.</returns>
public override Complex SumMagnitudes() public override Complex L1Norm()
{ {
double result = 0; double result = 0;
for (var i = 0; i < _storage.ValueCount; i++) for (var i = 0; i < _storage.ValueCount; i++)
{ {
result += _storage.Values[i].Magnitude; result += _storage.Values[i].Magnitude;
} }
return result; 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> /// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector. /// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary> /// </summary>
@ -790,11 +842,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary> /// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector. /// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <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++) 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++) for (var i = 0; i < _storage.ValueCount; i++)
{ {
var index = _storage.Indices[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); 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 #region Parse Functions
/// <summary> /// <summary>

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

@ -140,27 +140,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary> /// <summary>
/// Divides each element of the vector by a scalar and stores the result in the result vector. /// Divides each element of the vector by a scalar and stores the result in the result vector.
/// </summary> /// </summary>
/// <param name="scalar"> /// <param name="divisor">
/// The scalar to divide with. /// The scalar to divide with.
/// </param> /// </param>
/// <param name="result"> /// <param name="result">
/// The vector to store the result of the division. /// The vector to store the result of the division.
/// </param> /// </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> /// <summary>
/// Divides a scalar by each element of the vector and stores the result in the result vector. /// Divides a scalar by each element of the vector and stores the result in the result vector.
/// </summary> /// </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> /// <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++) 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> /// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector. /// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <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++) for (var index = 0; index < Count; index++)
{ {
result.At(index, At(index) / other.At(index)); result.At(index, At(index) / divisor.At(index));
} }
} }
/// <summary> /// <summary>
/// Pointwise modulus this vector with another vector and stores the result into the result vector. /// Pointwise modulus this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <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(); throw new NotSupportedException();
} }
@ -203,28 +203,37 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary> /// <summary>
/// Computes the dot product between this vector and another vector. /// Computes the dot product between this vector and another vector.
/// </summary> /// </summary>
/// <param name="other"> /// <param name="other">The other vector.</param>
/// The other vector to add. /// <returns>The sum of a[i]*b[i] for all i.</returns>
/// </param>
/// <returns>
/// The result of the addition.
/// </returns>
protected override Complex DoDotProduct(Vector<Complex> other) protected override Complex DoDotProduct(Vector<Complex> other)
{ {
var dot = Complex.Zero; var dot = Complex.Zero;
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
{ {
dot += At(i) * other.At(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; return dot;
} }
/// <summary> /// <summary>
/// Computes the modulus for each element of the vector for the given divisor. /// Computes the modulus for each element of the vector for the given divisor.
/// </summary> /// </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> /// <param name="result">A vector to store the results in.</param>
protected override void DoModulus(Complex divisor, Vector<Complex> result) protected override void DoModulus(Complex divisor, Vector<Complex> result)
{ {
@ -234,9 +243,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <summary> /// <summary>
/// Computes the modulus for the given dividend for each element of the vector. /// Computes the modulus for the given dividend for each element of the vector.
/// </summary> /// </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> /// <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(); throw new NotSupportedException();
} }
@ -308,31 +317,45 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override Complex Sum() public override Complex Sum()
{ {
var sum = Complex.Zero; var sum = Complex.Zero;
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
{ {
sum += At(i); sum += At(i);
} }
return sum; return sum;
} }
/// <summary> /// <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> /// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns> /// <returns>The sum of the absolute values.</returns>
public override Complex SumMagnitudes() public override Complex L1Norm()
{ {
var sum = Complex.Zero; var sum = Complex.Zero;
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
{ {
sum += At(i).Magnitude; sum += At(i).Magnitude;
} }
return sum; 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> /// <summary>
/// Computes the p-Norm. /// Computes the p-Norm.
/// </summary> /// </summary>
@ -344,23 +367,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// </returns> /// </returns>
public override Complex Norm(double p) public override Complex Norm(double p)
{ {
if (p < 0.0) if (p < 0d) throw new ArgumentOutOfRangeException("p");
{
throw new ArgumentOutOfRangeException("p");
}
if (double.IsPositiveInfinity(p)) if (p == 1d) return L1Norm();
{ if (p == 2d) return L2Norm();
return CommonParallel.Aggregate(0, Count, i => At(i).Magnitude, Math.Max, 0d); if (Double.IsPositiveInfinity(p)) return InfinityNorm();
}
var sum = 0.0;
var sum = 0d;
for (var index = 0; index < Count; index++) for (var index = 0; index < Count; index++)
{ {
sum += Math.Pow(At(index).Magnitude, p); sum += Math.Pow(At(index).Magnitude, p);
} }
return Math.Pow(sum, 1.0 / p); return Math.Pow(sum, 1.0 / p);
} }

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

@ -28,6 +28,8 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// </copyright> // </copyright>
using MathNet.Numerics.Threading;
namespace MathNet.Numerics.LinearAlgebra.Complex32 namespace MathNet.Numerics.LinearAlgebra.Complex32
{ {
using Algorithms.LinearAlgebra; 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> /// <summary>
/// Pointwise multiplies this matrix with 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> /// </summary>
@ -606,16 +626,16 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary> /// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary> /// </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> /// <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; var denseResult = result as DenseMatrix;
if (denseOther == null || denseResult == null) if (denseOther == null || denseResult == null)
{ {
base.DoPointwiseDivide(other, result); base.DoPointwiseDivide(divisor, result);
} }
else 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> /// <summary>
/// Adds another matrix to this matrix. /// Adds another matrix to this matrix.
/// </summary> /// </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> /// <summary>
/// Subtracts another matrix from this matrix. /// Subtracts another matrix from this matrix.
/// </summary> /// </summary>

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

@ -429,14 +429,33 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary> /// <summary>
/// Computes the dot product between this vector and another vector. /// Computes the dot product between this vector and another vector.
/// </summary> /// </summary>
/// <param name="other">The other vector to add.</param> /// <param name="other">The other vector.</param>
/// <returns>s /// <returns>The sum of a[i]*b[i] for all i.</returns>
/// The result of the addition.</returns>
protected override Complex32 DoDotProduct(Vector<Complex32> other) protected override Complex32 DoDotProduct(Vector<Complex32> other)
{ {
var denseVector = other as DenseVector; 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> /// <summary>
@ -575,31 +594,67 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override Complex32 Sum() public override Complex32 Sum()
{ {
var sum = Complex32.Zero; var sum = Complex32.Zero;
for (var i = 0; i < _length; i++) for (var i = 0; i < _length; i++)
{ {
sum += _values[i]; sum += _values[i];
} }
return sum; return sum;
} }
/// <summary> /// <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> /// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns> /// <returns>The sum of the absolute values.</returns>
public override Complex32 SumMagnitudes() public override Complex32 L1Norm()
{ {
var sum = Complex32.Zero; var sum = Complex32.Zero;
for (var i = 0; i < _length; i++) for (var i = 0; i < _length; i++)
{ {
sum += _values[i].Magnitude; sum += _values[i].Magnitude;
} }
return sum; 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> /// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector. /// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary> /// </summary>
@ -623,17 +678,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary> /// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector. /// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <param name="result">The vector to store the result of the pointwise division.</param>
/// <remarks></remarks> /// <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; var denseResult = result as DenseVector;
if (denseOther == null || denseResult == null) if (denseOther == null || denseResult == null)
{ {
base.DoPointwiseDivide(other, result); base.DoPointwiseDivide(divisor, result);
} }
else else
{ {
@ -688,43 +743,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return OuterProduct(this, v); 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 #region Parse Functions
/// <summary> /// <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++) 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) if (norm == 0.0f)
{ {
throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient); throw new ArgumentException(Resources.ArgumentMatrixNotRankDeficient);

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

@ -124,6 +124,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return norm; 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> /// <summary>
/// Adds another matrix to this matrix. /// Adds another matrix to this matrix.
/// </summary> /// </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> /// <summary>
/// Subtracts another matrix from this matrix. /// Subtracts another matrix from this matrix.
/// </summary> /// </summary>
@ -198,11 +230,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary> /// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix. /// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary> /// </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> /// <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> /// <summary>
@ -339,27 +387,47 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary> /// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary> /// </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> /// <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 j = 0; j < ColumnCount; j++)
{ {
for (var i = 0; i < RowCount; i++) 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> /// <summary>
/// Computes the modulus for each element of the matrix. /// Computes the modulus for each element of the matrix.
/// </summary> /// </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> /// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(Complex32 divisor, Matrix<Complex32> result) 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> /// <summary>

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

@ -71,23 +71,23 @@ 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 /// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator. /// iterator.
/// </summary> /// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined(); static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary> /// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default /// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used. /// pre-conditioner will be used.
/// </summary> /// </summary>
private IPreConditioner _preconditioner; IPreConditioner _preconditioner;
/// <summary> /// <summary>
/// The iterative process controller. /// The iterative process controller.
/// </summary> /// </summary>
private IIterator _iterator; IIterator _iterator;
/// <summary> /// <summary>
/// Indicates if the user has stopped the solver. /// Indicates if the user has stopped the solver.
/// </summary> /// </summary>
private bool _hasBeenStopped; bool _hasBeenStopped;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BiCgStab"/> class. /// Initializes a new instance of the <see cref="BiCgStab"/> class.
@ -96,7 +96,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// When using this constructor the solver will use the <see cref="IIterator"/> with /// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner. /// the standard settings and a default preconditioner.
/// </remarks> /// </remarks>
public BiCgStab() : this(null, null) public BiCgStab()
: this(null, null)
{ {
} }
@ -119,7 +120,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process. </param> /// <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. /// the standard settings.
/// </remarks> /// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param> /// <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> /// </summary>
public ICalculationStatus IterationResult public ICalculationStatus IterationResult
{ {
get get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
} }
/// <summary> /// <summary>
@ -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) // rho_(i-1) = r~^T r_(i-1) // dotproduct r~ and r_(i-1)
var oldRho = currentRho; var oldRho = currentRho;
currentRho = tempResiduals.DotProduct(residuals); currentRho = tempResiduals.ConjugateDotProduct(residuals);
// if (rho_(i-1) == 0) // METHOD FAILS // if (rho_(i-1) == 0) // METHOD FAILS
// If rho is only 1 ULP from zero then we fail. // If rho is only 1 ULP from zero then we fail.
@ -344,7 +344,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(vecPdash, nu); matrix.Multiply(vecPdash, nu);
// alpha_i = rho_(i-1)/ (r~^T nu_i) = rho / dotproduct(r~ and nu_i) // 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 // s = r_(i-1) - alpha_i nu_i
nu.Multiply(-alpha, temp); nu.Multiply(-alpha, temp);
@ -388,7 +388,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(vecSdash, temp); matrix.Multiply(vecSdash, temp);
// omega_i = temp^T s / temp^T 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^ // x_i = x_(i-1) + alpha_i p^ + omega_i s^
temp.Multiply(-omega, residuals); temp.Multiply(-omega, residuals);
@ -432,7 +432,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="residual">Residual values in <see cref="Vector"/>.</param> /// <param name="residual">Residual values in <see cref="Vector"/>.</param>
/// <param name="x">Instance of the <see cref="Vector"/> x.</param> /// <param name="x">Instance of the <see cref="Vector"/> x.</param>
/// <param name="b">Instance of the <see cref="Vector"/> b.</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 // -Ax = residual
matrix.Multiply(x, residual); matrix.Multiply(x, residual);
@ -452,7 +452,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="source">Source <see cref="Vector"/>.</param> /// <param name="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param> /// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns> /// <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) if (_hasBeenStopped)
{ {

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

@ -377,7 +377,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(temp, s); matrix.Multiply(temp, s);
// alpha_k = (r*_0 * r_k) / (r*_0 * s_k) // 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 // y_k = t_(k-1) - r_k - alpha_k * w_(k-1) + alpha_k s_k
s.Subtract(w, temp); s.Subtract(w, temp);
@ -399,7 +399,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
// c_k = A d_k // c_k = A d_k
matrix.Multiply(temp, c); 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 // 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 // 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 // to do at least one at the start to initialize the
// system, but we'll only have to take special measures // system, but we'll only have to take special measures
// if we don't do any so ... // if we don't do any so ...
var ctdot = c.DotProduct(t); var ctdot = c.ConjugateDotProduct(t);
Complex32 eta; Complex32 eta;
Complex32 sigma; Complex32 sigma;
if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber)) if (((_numberOfBiCgStabSteps == 0) && (iterationNumber == 0)) || ShouldRunBiCgStabSteps(iterationNumber))
@ -427,7 +427,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
} }
else else
{ {
var ydot = y.DotProduct(y); var ydot = y.ConjugateDotProduct(y);
// yDot can only be zero if y is a zero vector // 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 // 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; ydot = 1.0f;
} }
var ytdot = y.DotProduct(t); var ytdot = y.ConjugateDotProduct(t);
var cydot = c.DotProduct(y); var cydot = c.ConjugateDotProduct(y);
var denom = (cdot*ydot) - (cydot*cydot); 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) // 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. // 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 // w_k = c_k + beta_k s_k
s.Multiply(beta, temp2); s.Multiply(beta, temp2);

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

@ -68,39 +68,39 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <summary> /// <summary>
/// The default number of starting vectors. /// The default number of starting vectors.
/// </summary> /// </summary>
private const int DefaultNumberOfStartingVectors = 50; const int DefaultNumberOfStartingVectors = 50;
/// <summary> /// <summary>
/// The status used if there is no status, i.e. the solver hasn't run yet and there is no /// The status used if there is no status, i.e. the solver hasn't run yet and there is no
/// iterator. /// iterator.
/// </summary> /// </summary>
private static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined(); static readonly ICalculationStatus DefaultStatus = new CalculationIndetermined();
/// <summary> /// <summary>
/// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default /// The preconditioner that will be used. Can be set to <see langword="null" />, in which case the default
/// pre-conditioner will be used. /// pre-conditioner will be used.
/// </summary> /// </summary>
private IPreConditioner _preconditioner; IPreConditioner _preconditioner;
/// <summary> /// <summary>
/// The iterative process controller. /// The iterative process controller.
/// </summary> /// </summary>
private IIterator _iterator; IIterator _iterator;
/// <summary> /// <summary>
/// The collection of starting vectors which are used as the basis for the Krylov sub-space. /// The collection of starting vectors which are used as the basis for the Krylov sub-space.
/// </summary> /// </summary>
private IList<Vector> _startingVectors; IList<Vector> _startingVectors;
/// <summary> /// <summary>
/// The number of starting vectors used by the algorithm /// The number of starting vectors used by the algorithm
/// </summary> /// </summary>
private int _numberOfStartingVectors = DefaultNumberOfStartingVectors; int _numberOfStartingVectors = DefaultNumberOfStartingVectors;
/// <summary> /// <summary>
/// Indicates if the user has stopped the solver. /// Indicates if the user has stopped the solver.
/// </summary> /// </summary>
private bool _hasBeenStopped; bool _hasBeenStopped;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MlkBiCgStab"/> class. /// 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 /// When using this constructor the solver will use the <see cref="IIterator"/> with
/// the standard settings and a default preconditioner. /// the standard settings and a default preconditioner.
/// </remarks> /// </remarks>
public MlkBiCgStab() : this(null, null) public MlkBiCgStab()
: this(null, null)
{ {
} }
@ -132,7 +133,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// </para> /// </para>
/// </remarks> /// </remarks>
/// <param name="iterator">The <see cref="IIterator"/> that will be used to monitor the iterative process.</param> /// <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. /// the standard settings.
/// </remarks> /// </remarks>
/// <param name="preconditioner">The <see cref="IPreConditioner"/> that will be used to precondition the matrix equation.</param> /// <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 public int NumberOfStartingVectors
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return _numberOfStartingVectors; }
{
return _numberOfStartingVectors;
}
[DebuggerStepThrough] [DebuggerStepThrough]
set set
@ -231,10 +231,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
public IList<Vector> StartingVectors public IList<Vector> StartingVectors
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return _startingVectors; }
{
return _startingVectors;
}
[DebuggerStepThrough] [DebuggerStepThrough]
set set
@ -256,10 +253,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
public ICalculationStatus IterationResult public ICalculationStatus IterationResult
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get get { return (_iterator != null) ? _iterator.Status : DefaultStatus; }
{
return (_iterator != null) ? _iterator.Status : DefaultStatus;
}
} }
/// <summary> /// <summary>
@ -420,14 +414,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
matrix.Multiply(gtemp, w[k - 1]); matrix.Multiply(gtemp, w[k - 1]);
// c_((j-1)k+k) = q^T_1 w_((j-1)k+k) // 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)) 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"); 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) // 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) // u_(jk+1) = r_((j-1)k+k) - alpha_(jk+1) w_((j-1)k+k)
w[k - 1].Multiply(-alpha, temp); 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 // rho_(j+1) = -u^t_(jk+1) A u~_(jk+1) / ||A u~_(jk+1)||^2
matrix.Multiply(temp1, temp); 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 // If rho is zero then temp is a zero vector and we're probably
// about to have zero residuals (i.e. an exact solution). // 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 = 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) // r_(jk+1) = rho_(j+1) A u~_(jk+1) + u_(jk+1)
u.CopyTo(residuals); u.CopyTo(residuals);
@ -502,7 +496,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
for (var s = i; s < k - 1; s++) 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^(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) // z_d = z_d + beta^(jk+i)_((j-1)k+s) d_((j-1)k+s)
d[s].Multiply(beta, temp); d[s].Multiply(beta, temp);
@ -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)) // 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); zw.Multiply(rho, temp2);
residuals.Add(temp2, temp); 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) // z_g = z_g + beta^(jk+i)_((j-1)k+k) g_((j-1)k+k)
g[k - 1].Multiply(beta, temp); 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++) for (var s = 0; s < i - 1; s++)
{ {
// beta^(jk+i)_(jk+s) = -q^T_s+1 z_d / c_(jk+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) // z_d = z_d + beta^(jk+i)_(jk+s) * d_(jk+s)
d[s].Multiply(beta, temp); d[s].Multiply(beta, temp);
@ -573,14 +567,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
if (i < k - 1) if (i < k - 1)
{ {
// c_(jk+1) = q^T_i+1 d_(jk+i) // 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)) if (c[i].Real.AlmostEqual(0, 1) && c[i].Imaginary.AlmostEqual(0, 1))
{ {
throw new Exception("Iterative solver experience a numerical break down"); 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_(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) // u_(jk+i+1) = u_(jk+i) - alpha_(jk+i+1) d_(jk+i)
d[i].Multiply(-alpha, temp); d[i].Multiply(-alpha, temp);
@ -626,7 +620,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="maximumNumberOfStartingVectors">Maximum number</param> /// <param name="maximumNumberOfStartingVectors">Maximum number</param>
/// <param name="numberOfVariables">Number of variables</param> /// <param name="numberOfVariables">Number of variables</param>
/// <returns>Number of starting vectors to create</returns> /// <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 // Create no more starting vectors than the size of the problem - 1
return Math.Min(maximumNumberOfStartingVectors, (numberOfVariables - 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="numberOfVariables"/> is smaller than
/// the <paramref name="maximumNumberOfStartingVectors"/>. /// the <paramref name="maximumNumberOfStartingVectors"/>.
/// </returns> /// </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 // Create no more starting vectors than the size of the problem - 1
// Get random values and then orthogonalize them with // Get random values and then orthogonalize them with
@ -680,7 +674,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
result.Add((Vector) orthogonalMatrix.Column(i)); result.Add((Vector) orthogonalMatrix.Column(i));
// Normalize the result vector // 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; return result;
@ -692,7 +686,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
/// <param name="arraySize">Number of vectors</param> /// <param name="arraySize">Number of vectors</param>
/// <param name="vectorSize">Size of each vector</param> /// <param name="vectorSize">Size of each vector</param>
/// <returns>Array of random vectors</returns> /// <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]; var result = new Vector[arraySize];
for (var i = 0; i < result.Length; i++) 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="residual">Residual <see cref="Vector"/> data.</param>
/// <param name="x">x <see cref="Vector"/> data.</param> /// <param name="x">x <see cref="Vector"/> data.</param>
/// <param name="b">b <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 // -Ax = residual
matrix.Multiply(x, 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="source">Source <see cref="Vector"/>.</param>
/// <param name="residuals">Residual <see cref="Vector"/>.</param> /// <param name="residuals">Residual <see cref="Vector"/>.</param>
/// <returns><c>true</c> if continue, otherwise <c>false</c></returns> /// <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) if (_hasBeenStopped)
{ {

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 temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count); var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.Norm(2);
// Define the scalars // Define the scalars
Complex32 alpha = 0; Complex32 alpha = 0;
Complex32 eta = 0; Complex32 eta = 0;
float theta = 0; float theta = 0;
var tau = startNorm.Real; // Initialize
var tau = input.L2Norm().Real;
Complex32 rho = tau*tau; Complex32 rho = tau*tau;
// Calculate the initial values for v // Calculate the initial values for v
@ -311,7 +309,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
if (IsEven(iterationNumber)) if (IsEven(iterationNumber))
{ {
// sigma = (v, r) // 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)) if (sigma.Real.AlmostEqual(0, 1) && sigma.Imaginary.AlmostEqual(0, 1))
{ {
// FAIL HERE // FAIL HERE
@ -349,7 +347,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
yinternal.Add(temp, d); yinternal.Add(temp, d);
// theta = ||pseudoResiduals||_2 / tau // theta = ||pseudoResiduals||_2 / tau
theta = pseudoResiduals.Norm(2).Real/tau; theta = pseudoResiduals.L2Norm().Real/tau;
var c = 1/(float) Math.Sqrt(1 + (theta*theta)); var c = 1/(float) Math.Sqrt(1 + (theta*theta));
// tau = tau * theta * c // tau = tau * theta * c
@ -392,7 +390,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Solvers.Iterative
break; break;
} }
var rhoNew = pseudoResiduals.DotProduct(r.Conjugate()); var rhoNew = r.ConjugateDotProduct(pseudoResiduals);
var beta = rhoNew/rho; var beta = rhoNew/rho;
// Update rho for the next loop // 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 // pivot the row
PivotRow(workVector); PivotRow(workVector);
var vectorNorm = workVector.Norm(Double.PositiveInfinity); var vectorNorm = workVector.InfinityNorm();
// for j = 1, .. , i - 1) // for j = 1, .. , i - 1)
for (var j = 0; j < i; j++) 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 // 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. // 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. // Check if we have NaN's. If so we've gone way beyond normal divergence.
// Stop the iteration. // 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 // Store the infinity norms of both the solution and residual vectors
var residualNorm = residualVector.Norm(Double.PositiveInfinity); var residualNorm = residualVector.InfinityNorm();
var solutionNorm = solutionVector.Norm(Double.PositiveInfinity); var solutionNorm = solutionVector.InfinityNorm();
if (Single.IsNaN(solutionNorm.Real) || Single.IsNaN(residualNorm.Real)) 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 // Store the infinity norms of both the solution and residual vectors
// These values will be used to calculate the relative drop in residuals // These values will be used to calculate the relative drop in residuals
// later on. // later on.
var residualNorm = residualVector.Norm(float.PositiveInfinity); var residualNorm = residualVector.InfinityNorm();
// Check the residuals by calculating: // Check the residuals by calculating:
// ||r_i|| <= stop_tol * ||b|| // ||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. // First check that we have real numbers not NaN's.
// NaN's can occur when the iterative process diverges so we // 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> /// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary> /// </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> /// <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(); result.Clear();
@ -1067,7 +1067,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{ {
if (!values[j].IsZero()) 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> /// <summary>
/// Computes the dot product between this vector and another vector. /// Computes the dot product between this vector and another vector.
/// </summary> /// </summary>
/// <param name="other"> /// <param name="other">The other vector.</param>
/// The other vector to add. /// <returns>The sum of a[i]*b[i] for all i.</returns>
/// </param>
/// <returns>s
/// The result of the addition.
/// </returns>
protected override Complex32 DoDotProduct(Vector<Complex32> other) protected override Complex32 DoDotProduct(Vector<Complex32> other)
{ {
var result = Complex32.Zero; var result = Complex32.Zero;
if (ReferenceEquals(this, other)) if (ReferenceEquals(this, other))
{ {
for (var i = 0; i < _storage.ValueCount; i++) 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]); 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; return result;
} }
@ -739,25 +758,58 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{ {
result += _storage.Values[i]; result += _storage.Values[i];
} }
return result; return result;
} }
/// <summary> /// <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> /// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns> /// <returns>The sum of the absolute values.</returns>
public override Complex32 SumMagnitudes() public override Complex32 L1Norm()
{ {
var result = 0.0f; var result = 0f;
for (var i = 0; i < _storage.ValueCount; i++) for (var i = 0; i < _storage.ValueCount; i++)
{ {
result += _storage.Values[i].Magnitude; result += _storage.Values[i].Magnitude;
} }
return result; 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> /// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector. /// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary> /// </summary>
@ -785,11 +837,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary> /// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector. /// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <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++) 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++) for (var i = 0; i < _storage.ValueCount; i++)
{ {
var index = _storage.Indices[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); 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 #region Parse Functions
/// <summary> /// <summary>

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

@ -135,27 +135,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary> /// <summary>
/// Divides each element of the vector by a scalar and stores the result in the result vector. /// Divides each element of the vector by a scalar and stores the result in the result vector.
/// </summary> /// </summary>
/// <param name="scalar"> /// <param name="divisor">
/// The scalar to divide with. /// The scalar to divide with.
/// </param> /// </param>
/// <param name="result"> /// <param name="result">
/// The vector to store the result of the division. /// The vector to store the result of the division.
/// </param> /// </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> /// <summary>
/// Divides a scalar by each element of the vector and stores the result in the result vector. /// Divides a scalar by each element of the vector and stores the result in the result vector.
/// </summary> /// </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> /// <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++) 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> /// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector. /// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <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++) for (var index = 0; index < Count; index++)
{ {
result.At(index, At(index) / other.At(index)); result.At(index, At(index) / divisor.At(index));
} }
} }
/// <summary> /// <summary>
/// Pointwise modulus this vector with another vector and stores the result into the result vector. /// Pointwise modulus this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <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(); throw new NotSupportedException();
} }
@ -198,28 +198,37 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary> /// <summary>
/// Computes the dot product between this vector and another vector. /// Computes the dot product between this vector and another vector.
/// </summary> /// </summary>
/// <param name="other"> /// <param name="other">The other vector.</param>
/// The other vector to add. /// <returns>The sum of a[i]*b[i] for all i.</returns>
/// </param>
/// <returns>s
/// The result of the addition.
/// </returns>
protected override Complex32 DoDotProduct(Vector<Complex32> other) protected override Complex32 DoDotProduct(Vector<Complex32> other)
{ {
var dot = Complex32.Zero; var dot = Complex32.Zero;
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
{ {
dot += At(i) * other.At(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; return dot;
} }
/// <summary> /// <summary>
/// Computes the modulus for each element of the vector for the given divisor. /// Computes the modulus for each element of the vector for the given divisor.
/// </summary> /// </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> /// <param name="result">A vector to store the results in.</param>
protected override void DoModulus(Complex32 divisor, Vector<Complex32> result) protected override void DoModulus(Complex32 divisor, Vector<Complex32> result)
{ {
@ -229,9 +238,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <summary> /// <summary>
/// Computes the modulus for the given dividend for each element of the vector. /// Computes the modulus for the given dividend for each element of the vector.
/// </summary> /// </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> /// <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(); throw new NotSupportedException();
} }
@ -303,31 +312,45 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override Complex32 Sum() public override Complex32 Sum()
{ {
var sum = Complex32.Zero; var sum = Complex32.Zero;
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
{ {
sum += At(i); sum += At(i);
} }
return sum; return sum;
} }
/// <summary> /// <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> /// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns> /// <returns>The sum of the absolute values.</returns>
public override Complex32 SumMagnitudes() public override Complex32 L1Norm()
{ {
var sum = Complex32.Zero; var sum = Complex32.Zero;
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
{ {
sum += At(i).Magnitude; sum += At(i).Magnitude;
} }
return sum; 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> /// <summary>
/// Computes the p-Norm. /// Computes the p-Norm.
/// </summary> /// </summary>
@ -339,23 +362,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// </returns> /// </returns>
public override Complex32 Norm(double p) public override Complex32 Norm(double p)
{ {
if (p < 0.0) if (p < 0d) throw new ArgumentOutOfRangeException("p");
{
throw new ArgumentOutOfRangeException("p");
}
if (double.IsPositiveInfinity(p)) if (p == 1d) return L1Norm();
{ if (p == 2d) return L2Norm();
return CommonParallel.Aggregate(0, Count, i => At(i).Magnitude, Math.Max, 0f); if (Double.IsPositiveInfinity(p)) return InfinityNorm();
}
var sum = 0.0;
var sum = 0d;
for (var index = 0; index < Count; index++) for (var index = 0; index < Count; index++)
{ {
sum += Math.Pow(At(index).Magnitude, p); sum += Math.Pow(At(index).Magnitude, p);
} }
return (float) Math.Pow(sum, 1.0/p); return (float) Math.Pow(sum, 1.0/p);
} }

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

@ -392,6 +392,30 @@ namespace MathNet.Numerics.LinearAlgebra.Double
#endregion #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> /// <summary>
/// Adds another matrix to this matrix. /// Adds another matrix to this matrix.
/// </summary> /// </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> /// <summary>
/// Subtracts another matrix from this matrix. /// Subtracts another matrix from this matrix.
/// </summary> /// </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> /// <summary>
/// Pointwise multiplies this matrix with 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> /// </summary>
@ -646,16 +712,16 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary> /// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary> /// </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> /// <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; var denseResult = result as DenseMatrix;
if (denseOther == null || denseResult == null) if (denseOther == null || denseResult == null)
{ {
base.DoPointwiseDivide(other, result); base.DoPointwiseDivide(divisor, result);
} }
else 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> /// <summary>
/// Computes the trace of this matrix. /// Computes the trace of this matrix.
/// </summary> /// </summary>

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

@ -440,14 +440,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary> /// <summary>
/// Computes the dot product between this vector and another vector. /// Computes the dot product between this vector and another vector.
/// </summary> /// </summary>
/// <param name="other">The other vector to add.</param> /// <param name="other">The other vector.</param>
/// <returns>s /// <returns>The sum of a[i]*b[i] for all i.</returns>
/// The result of the addition.</returns>
protected override double DoDotProduct(Vector<double> other) protected override double DoDotProduct(Vector<double> other)
{ {
var denseVector = other as DenseVector; var denseVector = other as DenseVector;
return denseVector == null
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values); ? base.DoDotProduct(other)
: Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
} }
/// <summary> /// <summary>
@ -667,31 +667,67 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override double Sum() public override double Sum()
{ {
var sum = 0.0; var sum = 0.0;
for (var index = 0; index < _length; index++) for (var index = 0; index < _length; index++)
{ {
sum += _values[index]; sum += _values[index];
} }
return sum; return sum;
} }
/// <summary> /// <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> /// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns> /// <returns>The sum of the absolute values.</returns>
public override double SumMagnitudes() public override double L1Norm()
{ {
var sum = 0.0; var sum = 0d;
for (var index = 0; index < _length; index++) for (var index = 0; index < _length; index++)
{ {
sum += Math.Abs(_values[index]); sum += Math.Abs(_values[index]);
} }
return sum; 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> /// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector. /// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary> /// </summary>
@ -715,17 +751,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary> /// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector. /// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <param name="result">The vector to store the result of the pointwise division.</param>
/// <remarks></remarks> /// <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; var denseResult = result as DenseVector;
if (denseOther == null || denseResult == null) if (denseOther == null || denseResult == null)
{ {
base.DoPointwiseDivide(other, result); base.DoPointwiseDivide(divisor, result);
} }
else else
{ {
@ -780,46 +816,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return OuterProduct(this, v); 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 #region Parse Functions
/// <summary> /// <summary>

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

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

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

@ -114,6 +114,22 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return norm; 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> /// <summary>
/// Adds another matrix to this matrix. /// Adds another matrix to this matrix.
/// </summary> /// </summary>
@ -132,6 +148,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> /// <summary>
/// Subtracts another matrix from this matrix. /// Subtracts another matrix from this matrix.
/// </summary> /// </summary>
@ -188,11 +220,27 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary> /// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix. /// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary> /// </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 divisor, Matrix<double> 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> /// <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 DoDivideByThis(double dividend, Matrix<double> result)
{ {
DoMultiply(1.0 / scalar, result); for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, dividend / At(i, j));
}
}
} }
/// <summary> /// <summary>
@ -309,6 +357,38 @@ namespace MathNet.Numerics.LinearAlgebra.Double
CopyTo(result); 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> /// <summary>
/// Pointwise multiplies this matrix with 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> /// </summary>
@ -328,31 +408,31 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary> /// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary> /// </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> /// <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 j = 0; j < ColumnCount; j++)
{ {
for (var i = 0; i < RowCount; i++) 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> /// <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> /// </summary>
/// <param name="divisor">The divisor to use.</param> /// <param name="divisor">The pointwise denominator matrix to use</param>
/// <param name="result">Matrix to store the results in.</param> /// <param name="result">The result of the modulus.</param>
protected override void DoModulus(double divisor, Matrix<double> result) 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)); result.Add((Vector)orthogonalMatrix.Column(i));
// Normalize the result vector // 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; return result;

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

@ -281,15 +281,13 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers.Iterative
var temp1 = new DenseVector(input.Count); var temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count); var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.Norm(2);
// Define the scalars // Define the scalars
double alpha = 0; double alpha = 0;
double eta = 0; double eta = 0;
double theta = 0; double theta = 0;
var tau = startNorm; // Initialize
var tau = input.L2Norm();
var rho = tau*tau; var rho = tau*tau;
// Calculate the initial values for v // Calculate the initial values for v
@ -348,7 +346,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Solvers.Iterative
yinternal.Add(temp, d); yinternal.Add(temp, d);
// theta = ||pseudoResiduals||_2 / tau // theta = ||pseudoResiduals||_2 / tau
theta = pseudoResiduals.Norm(2) / tau; theta = pseudoResiduals.L2Norm() / tau;
var c = 1 / Math.Sqrt(1 + (theta * theta)); var c = 1 / Math.Sqrt(1 + (theta * theta));
// tau = tau * theta * c // 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 // pivot the row
PivotRow(workVector); PivotRow(workVector);
var vectorNorm = workVector.Norm(Double.PositiveInfinity); var vectorNorm = workVector.InfinityNorm();
// for j = 1, .. , i - 1) // for j = 1, .. , i - 1)
for (var j = 0; j < i; j++) 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 // 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. // 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. // Check if we have NaN's. If so we've gone way beyond normal divergence.
// Stop the iteration. // 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 // Store the infinity norms of both the solution and residual vectors
var residualNorm = residualVector.Norm(Double.PositiveInfinity); var residualNorm = residualVector.InfinityNorm();
var solutionNorm = solutionVector.Norm(Double.PositiveInfinity); var solutionNorm = solutionVector.InfinityNorm();
if (Double.IsNaN(solutionNorm) || Double.IsNaN(residualNorm)) 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 // Store the infinity norms of both the solution and residual vectors
// These values will be used to calculate the relative drop in residuals // These values will be used to calculate the relative drop in residuals
// later on. // later on.
var residualNorm = residualVector.Norm(Double.PositiveInfinity); var residualNorm = residualVector.InfinityNorm();
// Check the residuals by calculating: // Check the residuals by calculating:
// ||r_i|| <= stop_tol * ||b|| // ||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. // First check that we have real numbers not NaN's.
// NaN's can occur when the iterative process diverges so we // 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> /// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary> /// </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> /// <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(); result.Clear();
@ -1066,7 +1066,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{ {
if (values[j] != 0d) 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> /// <summary>
/// Computes the dot product between this vector and another vector. /// Computes the dot product between this vector and another vector.
/// </summary> /// </summary>
/// <param name="other"> /// <param name="other">The other vector.</param>
/// The other vector to add. /// <returns>The sum of a[i]*b[i] for all i.</returns>
/// </param>
/// <returns>s
/// The result of the addition.
/// </returns>
protected override double DoDotProduct(Vector<double> other) protected override double DoDotProduct(Vector<double> other)
{ {
var result = 0.0; var result = 0d;
if (ReferenceEquals(this, other)) if (ReferenceEquals(this, other))
{ {
for (var i = 0; i < _storage.ValueCount; i++) 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]); result += _storage.Values[i] * other.At(_storage.Indices[i]);
} }
} }
return result; return result;
} }
@ -775,25 +769,58 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{ {
result += _storage.Values[i]; result += _storage.Values[i];
} }
return result; return result;
} }
/// <summary> /// <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> /// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns> /// <returns>The sum of the absolute values.</returns>
public override double SumMagnitudes() public override double L1Norm()
{ {
double result = 0; var result = 0d;
for (var i = 0; i < _storage.ValueCount; i++) for (var i = 0; i < _storage.ValueCount; i++)
{ {
result += Math.Abs(_storage.Values[i]); result += Math.Abs(_storage.Values[i]);
} }
return result; 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> /// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector. /// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary> /// </summary>
@ -821,11 +848,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary> /// <summary>
/// Pointwise multiplies this vector with another vector and stores the result into the result vector. /// Pointwise multiplies this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <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++) 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++) for (var i = 0; i < _storage.ValueCount; i++)
{ {
var index = _storage.Indices[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); 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 #region Parse Functions
/// <summary> /// <summary>

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

@ -134,27 +134,27 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <summary> /// <summary>
/// Divides each element of the vector by a scalar and stores the result in the result vector. /// Divides each element of the vector by a scalar and stores the result in the result vector.
/// </summary> /// </summary>
/// <param name="scalar"> /// <param name="divisor">
/// The scalar to divide with. /// The scalar to divide with.
/// </param> /// </param>
/// <param name="result"> /// <param name="result">
/// The vector to store the result of the division. /// The vector to store the result of the division.
/// </param> /// </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> /// <summary>
/// Divides a scalar by each element of the vector and stores the result in the result vector. /// Divides a scalar by each element of the vector and stores the result in the result vector.
/// </summary> /// </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> /// <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++) 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> /// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector. /// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <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++) for (var index = 0; index < Count; index++)
{ {
result.At(index, At(index) / other.At(index)); result.At(index, At(index) / divisor.At(index));
} }
} }
/// <summary> /// <summary>
/// Pointwise modulus this vector with another vector and stores the result into the result vector. /// Pointwise modulus this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Vector<double> other, Vector<double> result) protected override void DoPointwiseModulus(Vector<double> divisor, 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)
{ {
for (var index = 0; index < Count; index++) for (var index = 0; index < Count; index++)
{ {
result.At(index, scalar % At(index)); result.At(index, At(index) % divisor.At(index));
} }
} }
/// <summary> /// <summary>
/// Computes the dot product between this vector and another vector. /// Computes the dot product between this vector and another vector.
/// </summary> /// </summary>
/// <param name="other"> /// <param name="other">The other vector.</param>
/// The other vector to add. /// <returns>The sum of a[i]*b[i] for all i.</returns>
/// </param>
/// <returns>s
/// The result of the addition.
/// </returns>
protected override double DoDotProduct(Vector<double> other) protected override double DoDotProduct(Vector<double> other)
{ {
var dot = 0.0; var dot = 0.0;
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
{ {
dot += At(i) * other.At(i); dot += At(i) * other.At(i);
} }
return dot; 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> /// <summary>
/// Computes the modulus for each element of the vector for the given divisor. /// Computes the modulus for each element of the vector for the given divisor.
/// </summary> /// </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> /// <param name="result">A vector to store the results in.</param>
protected override void DoModulus(double divisor, Vector<double> result) 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> /// <summary>
/// Returns the value of the absolute minimum element. /// Returns the value of the absolute minimum element.
/// </summary> /// </summary>
@ -311,31 +315,45 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override double Sum() public override double Sum()
{ {
var sum = 0.0; var sum = 0.0;
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
{ {
sum += At(i); sum += At(i);
} }
return sum; return sum;
} }
/// <summary> /// <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> /// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns> /// <returns>The sum of the absolute values.</returns>
public override double SumMagnitudes() public override double L1Norm()
{ {
var sum = 0.0; var sum = 0.0;
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
{ {
sum += Math.Abs(At(i)); sum += Math.Abs(At(i));
} }
return sum; 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> /// <summary>
/// Computes the p-Norm. /// Computes the p-Norm.
/// </summary> /// </summary>
@ -347,23 +365,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </returns> /// </returns>
public override double Norm(double p) public override double Norm(double p)
{ {
if (p < 0.0) if (p < 0d) throw new ArgumentOutOfRangeException("p");
{
throw new ArgumentOutOfRangeException("p");
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(0, Count, i => Math.Abs(At(i)), 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++) for (var index = 0; index < Count; index++)
{ {
sum += Math.Pow(Math.Abs(At(index)), p); sum += Math.Pow(Math.Abs(At(index)), p);
} }
return Math.Pow(sum, 1.0/p); return Math.Pow(sum, 1.0/p);
} }

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

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

1236
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 #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> /// <summary>
/// Adds another matrix to this matrix. /// Adds another matrix to this matrix.
/// </summary> /// </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> /// <summary>
/// Subtracts another matrix from this matrix. /// Subtracts another matrix from this matrix.
/// </summary> /// </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> /// <summary>
/// Pointwise multiplies this matrix with 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> /// </summary>
@ -646,16 +712,16 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary> /// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary> /// </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> /// <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; var denseResult = result as DenseMatrix;
if (denseOther == null || denseResult == null) if (denseOther == null || denseResult == null)
{ {
base.DoPointwiseDivide(other, result); base.DoPointwiseDivide(divisor, result);
} }
else 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> /// <summary>
/// Computes the trace of this matrix. /// Computes the trace of this matrix.
/// </summary> /// </summary>

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

@ -429,14 +429,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary> /// <summary>
/// Computes the dot product between this vector and another vector. /// Computes the dot product between this vector and another vector.
/// </summary> /// </summary>
/// <param name="other">The other vector to add.</param> /// <param name="other">The other vector.</param>
/// <returns>s /// <returns>The sum of a[i]*b[i] for all i.</returns>
/// The result of the addition.</returns>
protected override float DoDotProduct(Vector<float> other) protected override float DoDotProduct(Vector<float> other)
{ {
var denseVector = other as DenseVector; var denseVector = other as DenseVector;
return denseVector == null
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values); ? base.DoDotProduct(other)
: Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
} }
/// <summary> /// <summary>
@ -655,32 +655,68 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <returns>The sum of the vector's elements.</returns> /// <returns>The sum of the vector's elements.</returns>
public override float Sum() public override float Sum()
{ {
var sum = 0.0f; var sum = 0f;
for (var i = 0; i < _length; i++) for (var i = 0; i < _length; i++)
{ {
sum += _values[i]; sum += _values[i];
} }
return sum; return sum;
} }
/// <summary> /// <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> /// </summary>
/// <returns>The sum of the absolute value of the vector's elements.</returns> /// <returns>The sum of the absolute values.</returns>
public override float SumMagnitudes() public override float L1Norm()
{ {
var sum = 0.0f; var sum = 0f;
for (var i = 0; i < _length; i++) for (var i = 0; i < _length; i++)
{ {
sum += Math.Abs(_values[i]); sum += Math.Abs(_values[i]);
} }
return sum; 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> /// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector. /// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary> /// </summary>
@ -704,17 +740,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary> /// <summary>
/// Pointwise divide this vector with another vector and stores the result into the result vector. /// Pointwise divide this vector with another vector and stores the result into the result vector.
/// </summary> /// </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> /// <param name="result">The vector to store the result of the pointwise division.</param>
/// <remarks></remarks> /// <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; var denseResult = result as DenseVector;
if (denseOther == null || denseResult == null) if (denseOther == null || denseResult == null)
{ {
base.DoPointwiseDivide(other, result); base.DoPointwiseDivide(divisor, result);
} }
else else
{ {
@ -769,47 +805,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return OuterProduct(this, v); 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 #region Parse Functions
/// <summary> /// <summary>

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

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

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

@ -114,6 +114,22 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return norm; 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> /// <summary>
/// Adds another matrix to this matrix. /// Adds another matrix to this matrix.
/// </summary> /// </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> /// <summary>
/// Subtracts another matrix from this matrix. /// Subtracts another matrix from this matrix.
/// </summary> /// </summary>
@ -210,11 +242,27 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary> /// <summary>
/// Divides each element of the matrix by a scalar and places results into the result matrix. /// Divides each element of the matrix by a scalar and places results into the result matrix.
/// </summary> /// </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> /// <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> /// <summary>
@ -283,7 +331,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary> /// <summary>
/// Computes the modulus for each element of the matrix. /// Computes the modulus for each element of the matrix.
/// </summary> /// </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> /// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(float divisor, Matrix<float> result) 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> /// <summary>
/// Negate each element of this matrix and place the results into the result matrix. /// Negate each element of this matrix and place the results into the result matrix.
/// </summary> /// </summary>
@ -344,15 +408,31 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <summary> /// <summary>
/// Pointwise divide this matrix by another matrix and stores the result into the result matrix. /// Pointwise divide this matrix by another matrix and stores the result into the result matrix.
/// </summary> /// </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> /// <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 j = 0; j < ColumnCount; j++)
{ {
for (var i = 0; i < RowCount; i++) 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)); result.Add((Vector)orthogonalMatrix.Column(i));
// Normalize the result vector // 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; 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 temp1 = new DenseVector(input.Count);
var temp2 = new DenseVector(input.Count); var temp2 = new DenseVector(input.Count);
// Initialize
var startNorm = input.Norm(2);
// Define the scalars // Define the scalars
float alpha = 0; float alpha = 0;
float eta = 0; float eta = 0;
float theta = 0; float theta = 0;
var tau = startNorm; // Initialize
var tau = input.L2Norm();
var rho = tau*tau; var rho = tau*tau;
// Calculate the initial values for v // Calculate the initial values for v
@ -348,7 +346,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Solvers.Iterative
yinternal.Add(temp, d); yinternal.Add(temp, d);
// theta = ||pseudoResiduals||_2 / tau // theta = ||pseudoResiduals||_2 / tau
theta = pseudoResiduals.Norm(2)/tau; theta = pseudoResiduals.L2Norm()/tau;
var c = 1/(float) Math.Sqrt(1 + (theta*theta)); var c = 1/(float) Math.Sqrt(1 + (theta*theta));
// tau = tau * theta * c // 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 // pivot the row
PivotRow(workVector); PivotRow(workVector);
var vectorNorm = workVector.Norm(Double.PositiveInfinity); var vectorNorm = workVector.InfinityNorm();
// for j = 1, .. , i - 1) // for j = 1, .. , i - 1)
for (var j = 0; j < i; j++) 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 // 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. // 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. // Check if we have NaN's. If so we've gone way beyond normal divergence.
// Stop the iteration. // 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 // Store the infinity norms of both the solution and residual vectors
var residualNorm = residualVector.Norm(Double.PositiveInfinity); var residualNorm = residualVector.InfinityNorm();
var solutionNorm = solutionVector.Norm(Double.PositiveInfinity); var solutionNorm = solutionVector.InfinityNorm();
if (Double.IsNaN(solutionNorm) || Double.IsNaN(residualNorm)) if (Double.IsNaN(solutionNorm) || Double.IsNaN(residualNorm))
{ {

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

Loading…
Cancel
Save