diff --git a/MathNet.Numerics.sln b/MathNet.Numerics.sln
index 4b42186d..723672c5 100644
--- a/MathNet.Numerics.sln
+++ b/MathNet.Numerics.sln
@@ -51,6 +51,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{039229DA-A
docs\content\Interpolation.fsx = docs\content\Interpolation.fsx
docs\content\LinearEquations.fsx = docs\content\LinearEquations.fsx
docs\content\MKL.fsx = docs\content\MKL.fsx
+ docs\content\Probability.fsx = docs\content\Probability.fsx
docs\content\Random.fsx = docs\content\Random.fsx
docs\content\Regression.fsx = docs\content\Regression.fsx
docs\tools\templates\template.cshtml = docs\tools\templates\template.cshtml
diff --git a/docs/content/Probability.fsx b/docs/content/Probability.fsx
new file mode 100644
index 00000000..253e59dc
--- /dev/null
+++ b/docs/content/Probability.fsx
@@ -0,0 +1,272 @@
+(*** hide ***)
+#I "../../out/lib/net40"
+#r "MathNet.Numerics.dll"
+#r "MathNet.Numerics.FSharp.dll"
+open MathNet.Numerics.Random
+open MathNet.Numerics.Distributions
+
+(**
+Probability Distributions
+=========================
+
+Math.NET Numerics provides a wide range of probability distributions. Given the
+distribution parameters they can be used to investigate their statistical properties
+or to sample non-uniform random numbers.
+
+All the distributions implement a common set of operations such as
+evaluating the density (PDF) and the cumulative distribution (CDF)
+at a given point, or to compute the mean, standard deviation and other properties.
+Because it is often numerically more stable and faster to compute such statistical quantities
+in the logarithmic domain, we also provide a selection of them in the log domain with the "Ln" suffix,
+e.g. DensityLn for the logarithmic density.
+
+ [lang=csharp]
+ using MathNet.Numerics.Distributions;
+ using MathNet.Numerics.Random;
+
+ // create a parametrized distribution instance
+ var gamma = new Gamma(2.0, 1.5);
+
+ // distribution properties
+ double mean = gamma.Mean;
+ double variance = gamma.Variance;
+ double entropy = gamma.Entropy;
+
+ // distribution functions
+ double a = gamma.Density(2.3); // PDF
+ double b = gamma.DensityLn(2.3); // ln(PDF)
+ double c = gamma.CumulativeDistribution(0.7); // CDF
+
+ // non-uniform number sampling
+ double randomSample = gamma.Sample();
+
+Both probability functions and sampling are also available as static functions
+for simpler usage scenarios:
+
+ [lang=csharp]
+ // distribution parameters must be passed as arguments
+ double a2 = Gamma.PDF(2.0, 1.5, 2.3);
+ double randomSample2 = Gamma.Sample(2.0, 1.5);
+
+
+
+
+### Continuous Distributions
+
+* [Continuous Uniform](http://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29)
+* [Normal](http://en.wikipedia.org/wiki/Normal_distribution)
+* [Log Normal](http://en.wikipedia.org/wiki/Log-normal_distribution)
+* [Beta](http://en.wikipedia.org/wiki/Beta_distribution)
+* [Cauchy](http://en.wikipedia.org/wiki/cauchy_distribution) (Cauchy-Lorentz)
+* [Chi](http://en.wikipedia.org/wiki/Chi_distribution)
+* [Chi Squared](http://en.wikipedia.org/wiki/Chi-square_distribution)
+* [Erlang](http://en.wikipedia.org/wiki/Erlang_distribution)
+* [Exponential](http://en.wikipedia.org/wiki/exponential_distribution)
+* [Fisher-Snedecor](http://en.wikipedia.org/wiki/F-distribution) (F-Distribution)
+* [Gamma](http://en.wikipedia.org/wiki/Gamma_distribution)
+* [Inverse Gamma](http://en.wikipedia.org/wiki/inverse-gamma_distribution)
+* [Laplace](http://en.wikipedia.org/wiki/Laplace_distribution)
+* [Pareto](http://en.wikipedia.org/wiki/Pareto_distribution)
+* [Rayleigh](http://en.wikipedia.org/wiki/Rayleigh_distribution)
+* [Stable](http://en.wikipedia.org/wiki/Stable_distribution)
+* [Stundent-T](http://en.wikipedia.org/wiki/Student%27s_t-distribution)
+* [Weibull](http://en.wikipedia.org/wiki/Weibull_distribution)
+* [Triangular](https://en.wikipedia.org/wiki/Triangular_distribution)
+
+
+
+
+### Discrete Distributions
+
+* [Discrete Uniform](http://en.wikipedia.org/wiki/Uniform_distribution_%28discrete%29)
+* [Bernoulli](http://en.wikipedia.org/wiki/Bernoulli_distribution)
+* [Binomial](http://en.wikipedia.org/wiki/Binomial_distribution)
+* [Negative Binomial](http://en.wikipedia.org/wiki/Negative_binomial_distribution)
+* [Geometric](http://en.wikipedia.org/wiki/geometric_distribution)
+* [Hypergeometric](http://en.wikipedia.org/wiki/Hypergeometric_distribution)
+* [Poisson](http://en.wikipedia.org/wiki/Poisson_distribution)
+* [Categorical](http://en.wikipedia.org/wiki/Categorical_distribution)
+* [Conway-Maxwell-Poisson](http://en.wikipedia.org/wiki/Conway%E2%80%93Maxwell%E2%80%93Poisson_distribution)
+* [Zipf](http://en.wikipedia.org/wiki/Zipf%27s_law)
+
+### Multivariate Distributions
+
+* [Dirichlet](http://en.wikipedia.org/wiki/Dirichlet_distribution)
+* [Inverse Wishart](http://en.wikipedia.org/wiki/Inverse-Wishart_distribution)
+* [Matrix Normal](http://en.wikipedia.org/wiki/Matrix_normal_distribution)
+* [Multinomial](http://en.wikipedia.org/wiki/Multinomial_distribution)
+* [Normal Gamma](http://en.wikipedia.org/wiki/Normal-gamma_distribution)
+* [Wishart](http://en.wikipedia.org/wiki/Wishart_distribution)
+
+
+
+
+
+Distribution Parameters
+-----------------------
+
+There are many ways to parametrize a distribution in the literature. When using the
+default constructor, read carefully which parameters it requires. For distributions where
+multiple ways are common there are also static methods, so you can use the one that fits best.
+For example, a normal distribution is usually parametrized with mean and standard deviation,
+but if you'd rather use mean and precision:
+
+ [lang=csharp]
+ var normal = Normal.WithMeanPrecision(0.0, 0.5);
+
+Since probability distributions can also be sampled to generate random numbers
+with the configured distribution, all constructors optionally accept a random generator
+as last argument.
+
+ [lang=csharp]
+ var gamma2 = new Gamma(2.0, 1.5, new MersenneTwister());
+
+ // the random generator can also be replaced on an existing instance
+ gamma2.RandomSource = new Mrg32k3a();
+
+A few more examples, this time in F#:
+*)
+
+// some probability distributions
+let normal = Normal.WithMeanVariance(3.0, 1.5, a)
+let exponential = Exponential(2.4)
+let gamma = Gamma(2.0, 1.5, Random.crypto())
+let cauchy = Cauchy(0.0, 1.0, Random.mrg32k3aWith 10 false)
+let poisson = Poisson(3.0)
+let geometric = Geometric(0.8, Random.system())
+
+(**
+Some of the distributions also have routines for maximum-likelihood parameter
+estimation from a set of samples:
+*)
+
+let estimation = LogNormal.Estimate([| 2.0; 1.5; 2.1; 1.2; 3.0; 2.4; 1.8 |])
+let mean, variance = estimation.Mean, estimation.Variance
+let moreSamples = estimation.Samples() |> Seq.take 10 |> Seq.toArray
+
+(**
+or in C#:
+
+ [lang=csharp]
+ LogNormal estimation = LogNormal.Estimate(new [] {2.0, 1.5, 2.1, 1.2, 3.0, 2.4, 1.8});
+ double mean = estimation.Mean, variance = estimation.Variance;
+ double[] moreSamples = estimation.Samples().Take(10).ToArray();
+
+
+Sampling a Probability Distribution
+-----------------------------------
+
+Each distribution provides methods to generate random numbers from that distribution.
+These random variate generators work by accessing the distribution's member RandomSource
+to provide uniform random numbers. By default, this member is an instance of System.Random
+but one can easily replace this with more sophisticated random number generators from
+`MathNet.Numerics.Random` (see [Random Numbers](Random.html) for details).
+
+*)
+
+// sample some random numbers from these distributions
+// continuous distributions sample to floating-point numbers:
+let continuous =
+ [ yield normal.Sample()
+ yield exponential.Sample()
+ yield! gamma.Samples() |> Seq.take 10 ]
+
+// discrete distributions on the other hand sample to integers:
+let discrete =
+ [ poisson.Sample()
+ poisson.Sample()
+ geometric.Sample() ]
+
+(**
+
+Instead of creating a distribution object we can also sample directly with static functions.
+Note that no intermediate value caching is possible this way and parameters must be validated on each call.
+
+*)
+
+// using the default number generator (SystemRandomSource.Default)
+let w = Rayleigh.Sample(1.5)
+let x = Hypergeometric.Sample(100, 20, 5)
+
+// or by manually providing the uniform random number generator
+let u = Normal.Sample(Random.system(), 2.0, 4.0)
+let v = Laplace.Samples(Random.mersenneTwister(), 1.0, 3.0) |> Seq.take 100 |> List.ofSeq
+
+
+(**
+
+If you need to sample not just one or two values but a large number of them,
+there are routines that either fill an existing array or return an enumerable.
+The variant that fills an array is generally the fastest. Routines to sample
+more than one value use the plural form `Samples` instead of `Sample`.
+
+Let's sample 100'000 values from a laplace distribution with mean 1.0 and scale 2.0 in C#:
+
+ [lang=csharp]
+ var samples = new double[100000];
+ Laplace.Samples(samples, 1.0, 2.0);
+
+Let's do some random walks in F# (TODO: Graph):
+*)
+
+Seq.scan (+) 0.0 (Normal.Samples(0.0, 1.0)) |> Seq.take 10 |> Seq.toArray
+Seq.scan (+) 0.0 (Cauchy.Samples(0.0, 1.0)) |> Seq.take 10 |> Seq.toArray
+
+(**
+Distribution Functions and Properties
+-------------------------------------
+
+Distributions can not just be used to generate non-uniform random samples.
+Once parametrized they can compute a variety of distribution properties
+or evaluate distribution functions. Because it is often numerically more stable
+and faster to compute and work with such quantities in the logarithmic domain,
+some of them are also available with the `Ln`-suffix.
+*)
+
+// distribution properties of the gamma we've configured above
+let gammaStats =
+ ( gamma.Mean,
+ gamma.Variance,
+ gamma.StdDev,
+ gamma.Entropy,
+ gamma.Skewness,
+ gamma.Mode )
+
+// probability distribution functions of the normal we've configured above.
+let nd = normal.Density(4.0) (* PDF *)
+let ndLn = normal.DensityLn(4.0) (* ln(PDF) *)
+let nc = normal.CumulativeDistribution(4.0) (* CDF *)
+let nic = normal.InverseCumulativeDistribution(0.7) (* CDF^(-1) *)
+
+// Distribution functions can also be evaluated without creating an object,
+// but then you have to pass in the distribution parameters as first arguments:
+let nd2 = Normal.PDF(3.0, sqrt 1.5, 4.0)
+let ndLn2 = Normal.PDFLn(3.0, sqrt 1.5, 4.0)
+let nc2 = Normal.CDF(3.0, sqrt 1.5, 4.0)
+let nic2 = Normal.InvCDF(3.0, sqrt 1.5, 0.7)
+
+(**
+Composing Distributions
+-----------------------
+
+Specifically for F# there is also a `Sample` module that allows a somewhat more functional
+view on distribution sampling functions by having the random source passed in as last argument.
+This way they can be composed and transformed arbitrarily if curried:
+*)
+
+/// Transform a sample from a distribution
+let s1 rng = tanh (Sample.normal 2.0 0.5 rng)
+
+/// But we really want to transform the function, not the resulting sample:
+let s1f rng = Sample.map tanh (Sample.normal 2.0 0.5) rng
+
+/// Exactly the same also works with functions generating full sequences
+let s1s rng = Sample.mapSeq tanh (Sample.normalSeq 2.0 0.5) rng
+
+/// Now with multiple distributions, e.g. their product:
+let s2 rng = (Sample.normal 2.0 1.5 rng) * (Sample.cauchy 2.0 0.5 rng)
+let s2f rng = Sample.map2 (*) (Sample.normal 2.0 1.5) (Sample.cauchy 2.0 0.5) rng
+let s2s rng = Sample.mapSeq2 (*) (Sample.normalSeq 2.0 1.5) (Sample.cauchySeq 2.0 0.5) rng
+
+// Taking some samples from the composed function
+Seq.take 10 (s2s (Random.system())) |> Seq.toArray
diff --git a/docs/content/Random.fsx b/docs/content/Random.fsx
index e3b6bc84..41b89b36 100644
--- a/docs/content/Random.fsx
+++ b/docs/content/Random.fsx
@@ -6,8 +6,8 @@ open MathNet.Numerics.Random
open MathNet.Numerics.Distributions
(**
-Random Numbers and Probability Distributions
-============================================
+Pseudo-Random Numbers
+=====================
The .Net Framework base class library (BCL) includes a pseudo-random number generator
for non-cryptography use in the form of the `System.Random` class.
@@ -233,132 +233,24 @@ let b = Random.mersenneTwisterShared
let c = Random.shared;
(**
-Probability Distributions
--------------------------
+Non-Uniform Random Numbers
+--------------------------
For non-uniform random number generation you can use the wide range of probability
distributions in the `MathNet.Numerics.Distributions` namespace.
-There are many ways to parametrize a distribution in the literature. When using the
-default constructor, read carefully which parameters it requires. For distributions where
-multiple ways are common there are also static methods, so you can use the one that fits best.
-For example, a normal distribution is usually parametrized with mean and standard deviation,
-but if you'd rather use mean and precision:
-
- [lang=csharp]
- var normal = Normal.WithMeanPrecision(0.0, 0.5);
-
-Since probability distributions can also be sampled to generate random numbers
-with the configured distribution, all constructors optionally accept a random generator
-as last argument. A few more examples, this time in F#:
-*)
-
-// some probability distributions
-let normal = Normal.WithMeanVariance(3.0, 1.5, a)
-let exponential = Exponential(2.4)
-let gamma = Gamma(2.0, 1.5, Random.crypto())
-let cauchy = Cauchy(0.0, 1.0, Random.mrg32k3aWith 10 false)
-let poisson = Poisson(3.0)
-let geometric = Geometric(0.8, Random.system())
-
-// sample some random numbers from these distributions
-let continuous =
- [ yield normal.Sample()
- yield exponential.Sample()
- yield! gamma.Samples() |> Seq.take 10 ]
-
-let discrete =
- [ poisson.Sample()
- poisson.Sample()
- geometric.Sample() ]
-
-// direct sampling (without creating a distribution object)
-let u = Normal.Sample(Random.system(), 2.0, 4.0)
-let v = Laplace.Samples(Random.mersenneTwister(), 1.0, 3.0) |> Seq.take 100 |> List.ofSeq
-let w = Rayleigh.Sample(c, 1.5)
-let x = Hypergeometric.Sample(b, 100, 20, 5)
-
-(**
-Distribution Functions and Properties
--------------------------------------
-
-Distributions can not just be used to generate non-uniform random samples.
-Once parametrized they can compute a variety of distribution properties
-or evaluate distribution functions. Because it is often numerically more stable
-and faster to compute and work with such quantities in the logarithmic domain,
-some of them are also available with the `Ln`-suffix.
-*)
-
-// distribution properties of the gamma we've configured above
-let gammaStats =
- ( gamma.Mean,
- gamma.Variance,
- gamma.StdDev,
- gamma.Entropy,
- gamma.Skewness,
- gamma.Mode )
-
-// probability distribution functions of the normal we've configured above.
-let nd = normal.Density(4.0) (* pdf *)
-let ndLn = normal.DensityLn(4.0) (* ln(pdf) *)
-let nc = normal.CumulativeDistribution(4.0) (* cdf *)
-let nic = normal.InverseCumulativeDistribution(0.7) (* invcdf *)
-
-// Distribution functions can also be evaluated without creating an object,
-// but then you have to pass in the distribution parameters as first arguments:
-let nd2 = Normal.PDF(3.0, sqrt 1.5, 4.0)
-let ndLn2 = Normal.PDFLn(3.0, sqrt 1.5, 4.0)
-let nc2 = Normal.CDF(3.0, sqrt 1.5, 4.0)
-let nic2 = Normal.InvCDF(3.0, sqrt 1.5, 0.7)
-
-(**
-Some of the distributions also have routines for maximum-likelihood parameter
-estimation from a set of samples:
-*)
-
-let estimation = LogNormal.Estimate([| 2.0; 1.5; 2.1; 1.2; 3.0; 2.4; 1.8 |])
-let mean, variance = estimation.Mean, estimation.Variance
-let moreSamples = estimation.Samples() |> Seq.take 10 |> Seq.toArray
-
-(**
-or in C#:
-
[lang=csharp]
- LogNormal estimation = LogNormal.Estimate(new [] {2.0, 1.5, 2.1, 1.2, 3.0, 2.4, 1.8});
- double mean = estimation.Mean, variance = estimation.Variance;
- double[] moreSamples = estimation.Samples().Take(10).ToArray();
+ using MathNet.Numerics.Distributions;
-Let's do some random walks, using distributions and random sources defined above (TODO: Graph):
-*)
+ // sample a single value from a standard distribution
+ double a = Normal.Sample(0.0, 1.0);
-Seq.scan (+) 0.0 (normal.Samples()) |> Seq.take 10 |> Seq.toArray
-Seq.scan (+) 0.0 (Sample.normalSeq 0.0 0.5 a) |> Seq.take 10 |> Seq.toArray
+ // sample using a custom random number generator
+ double b = Normal.Sample(new MersenneTwister(), 0.0, 1.0);
-(**
-Composing Distributions
------------------------
+ // sample a large number of values in one go
+ double[] c = new double[100000];
+ Normal.Samples(c, 0.0, 1.0);
-Specifically for F# there is also a `Sample` module that allows a somewhat more functional
-view on distribution sampling functions by having the random source passed in as last argument.
-This way they can be composed and transformed arbitrarily if curried:
+See [Probability Distributions](Probability.html) for details.
*)
-
-/// Transform a sample from a distribution
-let s1 rng = tanh (Sample.normal 2.0 0.5 rng)
-
-/// But we really want to transform the function, not the resulting sample:
-let s1f rng = Sample.map tanh (Sample.normal 2.0 0.5) rng
-
-/// Exactly the same also works with functions generating full sequences
-let s1s rng = Sample.mapSeq tanh (Sample.normalSeq 2.0 0.5) rng
-
-/// Now with multiple distributions, e.g. their product:
-let s2 rng = (Sample.normal 2.0 1.5 rng) * (Sample.cauchy 2.0 0.5 rng)
-let s2f rng = Sample.map2 (*) (Sample.normal 2.0 1.5) (Sample.cauchy 2.0 0.5) rng
-let s2s rng = Sample.mapSeq2 (*) (Sample.normalSeq 2.0 1.5) (Sample.cauchySeq 2.0 0.5) rng
-
-// Taking some samples from the composed function
-Seq.take 10 (s2s (Random.system())) |> Seq.toArray
-
-// The random walk from above, but this time using the composition from above
-Seq.scan (+) 0.0 (s1s a) |> Seq.take 10 |> Seq.toArray
diff --git a/docs/tools/templates/template.cshtml b/docs/tools/templates/template.cshtml
index 38387ca8..2a860edb 100644
--- a/docs/tools/templates/template.cshtml
+++ b/docs/tools/templates/template.cshtml
@@ -67,7 +67,7 @@
Descriptive Statistics
- Probability Distributions
+ Probability Distributions
Generating Data