@ -1,4 +1,4 @@
// <copyright file="Gamma.cs" company="Math.NET">
// <copyright file="Gamma.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
@ -46,7 +46,7 @@ namespace MathNet.Numerics.Distributions
/// with shape and inverse scale both zero is undefined.</para>
/// <para> Random number generation for the Gamma distribution is based on the algorithm in:
/// "A Simple Method for Generating Gamma Variables" - Marsaglia & Tsang
/// ACM Transactions on Mathematical Software, Vol. 26, No. 3, September 2000, Pages 363–372.</para>
/// ACM Transactions on Mathematical Software, Vol. 26, No. 3, September 2000, Pages 363–372.</para>
/// <para>The distribution will use the <see cref="System.Random"/> by default.
/// Users can get/set the random number generator by using the <see cref="RandomSource"/> property.</para>
/// <para>The statistics classes will check all the incoming parameters whether they are in the allowed
@ -57,38 +57,37 @@ namespace MathNet.Numerics.Distributions
System . Random _ random ;
double _ shape ;
double _ invScal e;
double _ rat e;
/// <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>
public Gamma ( double shape , double invScal e)
/// <param name="shape">The shape (k, α) of the Gamma distribution.</param>
/// <param name="rate">The rate or inverse scale (β) of the Gamma distribution.</param>
public Gamma ( double shape , double rat e)
{
_ random = new System . Random ( ) ;
SetParameters ( shape , invScal e) ;
SetParameters ( shape , rat e) ;
}
/// <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="shape">The shape (k, α) of the Gamma distribution.</param>
/// <param name="rate">The rate or 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 invScal e, System . Random randomSource )
public Gamma ( double shape , double rat e, System . Random randomSource )
{
_ random = randomSource ? ? new System . Random ( ) ;
SetParameters ( shape , invScal e) ;
SetParameters ( shape , rat e) ;
}
/// <summary>
/// Constructs a Gamma distribution from a shape and scale parameter. The distribution will
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
/// </summary>
/// <param name="shape">The shape of the Gamma distribution.</param>
/// <param name="scale">The scale of the Gamma distribution.</param>
/// <returns>a normal distribution.</returns>
/// <param name="shape">The shape (k) of the Gamma distribution.</param>
/// <param name="scale">The scale (θ) of the Gamma distribution.</param>
public static Gamma WithShapeScale ( double shape , double scale )
{
return new Gamma ( shape , 1.0 / scale ) ;
@ -98,12 +97,11 @@ namespace MathNet.Numerics.Distributions
/// Constructs a Gamma distribution from a shape and inverse scale parameter. The distribution will
/// be initialized with the default <seealso cref="System.Random"/> random number generator.
/// </summary>
/// <param name="shape">The shape of the Gamma distribution.</param>
/// <param name="invScale">The inverse scale of the Gamma distribution.</param>
/// <returns>a normal distribution.</returns>
public static Gamma WithShapeInvScale ( double shape , double invScale )
/// <param name="shape">The shape (α) of the Gamma distribution.</param>
/// <param name="rate">The rate or inverse scale (β) of the Gamma distribution.</param>
public static Gamma WithShapeRate ( double shape , double rate )
{
return new Gamma ( shape , invScal e) ;
return new Gamma ( shape , rat e) ;
}
/// <summary>
@ -112,81 +110,79 @@ namespace MathNet.Numerics.Distributions
/// <returns>a string representation of the distribution.</returns>
public override string ToString ( )
{
return "Gamma(Shape = " + _ shape + ", Inverse Scale = " + _ invScal e + ")" ;
return "Gamma(α = " + _ shape + ", β = " + _ rat e + ")" ;
}
/// <summary>
/// Checks whether the parameters of the distribution are valid.
/// </summary>
/// <param name="shape">The shape of the Gamma distribution.</param>
/// <param name="invScale">The inverse scale of the Gamma distribution.</param>
/// <param name="shape">The shape (k, α) of the Gamma distribution.</param>
/// <param name="rate">The rate or inverse scale (β) of the Gamma distribution.</param>
/// <returns><c>true</c> when the parameters are valid, <c>false</c> otherwise.</returns>
static bool IsValidParameterSet ( double shape , double invScal e)
static bool IsValidParameterSet ( double shape , double rat e)
{
return shape > = 0.0 & & invScal e > = 0.0 ;
return shape > = 0.0 & & rat e > = 0.0 ;
}
/// <summary>
/// Sets the parameters of the distribution after checking their validity.
/// </summary>
/// <param name="shape">The shape of the Gamma distribution.</param>
/// <param name="invScale">The inverse scale of the Gamma distribution.</param>
/// <param name="shape">The shape (k, α) of the Gamma distribution.</param>
/// <param name="rate">The rate or inverse scale (β) of the Gamma distribution.</param>
/// <exception cref="ArgumentOutOfRangeException">When the parameters don't pass the <see cref="IsValidParameterSet"/> function.</exception>
void SetParameters ( double shape , double invScal e)
void SetParameters ( double shape , double rat e)
{
if ( Control . CheckDistributionParameters & & ! IsValidParameterSet ( shape , invScal e) )
if ( Control . CheckDistributionParameters & & ! IsValidParameterSet ( shape , rat e) )
{
throw new ArgumentOutOfRangeException ( Resources . InvalidDistributionParameters ) ;
}
_ shape = shape ;
_ invScale = invScal e;
_ rate = rat e;
}
/// <summary>
/// Gets or sets the random number generator which is used to draw random samples .
/// Gets or sets the shape (k, α) of the Gamma distribution .
/// </summary>
public System . Random RandomSourc e
public double Shap e
{
get { return _ random ; }
set { _ random = value ? ? new System . Random ( ) ; }
get { return _ shape ; }
set { SetParameters ( value , _ rate ) ; }
}
/// <summary>
/// Gets or sets the shape of the Gamma distribution.
/// Gets or sets the rate or inverse scale (β) of the Gamma distribution.
/// </summary>
public double Shap e
public double Rat e
{
get { return _ shap e; }
set { SetParameters ( value , _ invScal e) ; }
get { return _ rat e; }
set { SetParameters ( _ shape , valu e) ; }
}
/// <summary>
/// Gets or sets the scale of the Gamma distribution.
/// Gets or sets the scale (θ) of the Gamma distribution.
/// </summary>
public double Scale
{
get { return 1.0 / _ invScal e; }
get { return 1.0 / _ rat e ; }
set
{
var invScale = 1.0 / value ;
if ( Double . IsNegativeInfinity ( invScale ) )
var rate = 1.0 / value ;
if ( Double . IsNegativeInfinity ( rate ) )
{
invScale = - invScal e;
rate = - rat e;
}
SetParameters ( _ shape , invScale ) ;
SetParameters ( _ shape , rate ) ;
}
}
/// <summary>
/// Gets or sets the inverse scale of the Gamma distribution .
/// Gets or sets the random number generator which is used to draw random samples .
/// </summary>
public double InvScal e
public System . Random RandomSourc e
{
get { return _ invScale ; }
set { SetParameters ( _ shape , value ) ; }
get { return _ random ; }
set { _ random = value ? ? new System . Random ( ) ; }
}
/// <summary>
@ -196,17 +192,17 @@ namespace MathNet.Numerics.Distributions
{
get
{
if ( Double . IsPositiveInfinity ( _ invScal e) )
if ( Double . IsPositiveInfinity ( _ rat e) )
{
return _ shape ;
}
if ( _ invScal e = = 0.0 & & _ shape = = 0.0 )
if ( _ rat e = = 0.0 & & _ shape = = 0.0 )
{
return Double . NaN ;
}
return _ shape / _ invScal e;
return _ shape / _ rat e;
}
}
@ -217,17 +213,17 @@ namespace MathNet.Numerics.Distributions
{
get
{
if ( Double . IsPositiveInfinity ( _ invScal e) )
if ( Double . IsPositiveInfinity ( _ rat e) )
{
return 0.0 ;
}
if ( _ invScal e = = 0.0 & & _ shape = = 0.0 )
if ( _ rat e = = 0.0 & & _ shape = = 0.0 )
{
return Double . NaN ;
}
return _ shape / ( _ invScale * _ invScal e) ;
return _ shape / ( _ rate * _ rat e) ;
}
}
@ -238,17 +234,17 @@ namespace MathNet.Numerics.Distributions
{
get
{
if ( Double . IsPositiveInfinity ( _ invScal e) )
if ( Double . IsPositiveInfinity ( _ rat e) )
{
return 0.0 ;
}
if ( _ invScal e = = 0.0 & & _ shape = = 0.0 )
if ( _ rat e = = 0.0 & & _ shape = = 0.0 )
{
return Double . NaN ;
}
return Math . Sqrt ( _ shape / ( _ invScale * _ invScal e) ) ;
return Math . Sqrt ( _ shape / ( _ rate * _ rat e) ) ;
}
}
@ -259,17 +255,17 @@ namespace MathNet.Numerics.Distributions
{
get
{
if ( Double . IsPositiveInfinity ( _ invScal e) )
if ( Double . IsPositiveInfinity ( _ rat e) )
{
return 0.0 ;
}
if ( _ invScal e = = 0.0 & & _ shape = = 0.0 )
if ( _ rat e = = 0.0 & & _ shape = = 0.0 )
{
return Double . NaN ;
}
return _ shape - Math . Log ( _ invScal e) + SpecialFunctions . GammaLn ( _ shape ) + ( ( 1.0 - _ shape ) * SpecialFunctions . DiGamma ( _ shape ) ) ;
return _ shape - Math . Log ( _ rat e) + SpecialFunctions . GammaLn ( _ shape ) + ( ( 1.0 - _ shape ) * SpecialFunctions . DiGamma ( _ shape ) ) ;
}
}
@ -280,12 +276,12 @@ namespace MathNet.Numerics.Distributions
{
get
{
if ( Double . IsPositiveInfinity ( _ invScal e) )
if ( Double . IsPositiveInfinity ( _ rat e) )
{
return 0.0 ;
}
if ( _ invScal e = = 0.0 & & _ shape = = 0.0 )
if ( _ rat e = = 0.0 & & _ shape = = 0.0 )
{
return Double . NaN ;
}
@ -301,17 +297,17 @@ namespace MathNet.Numerics.Distributions
{
get
{
if ( Double . IsPositiveInfinity ( _ invScal e) )
if ( Double . IsPositiveInfinity ( _ rat e) )
{
return _ shape ;
}
if ( _ invScal e = = 0.0 & & _ shape = = 0.0 )
if ( _ rat e = = 0.0 & & _ shape = = 0.0 )
{
return Double . NaN ;
}
return ( _ shape - 1.0 ) / _ invScal e;
return ( _ shape - 1.0 ) / _ rat e;
}
}
@ -346,22 +342,22 @@ namespace MathNet.Numerics.Distributions
/// <returns>the density at <paramref name="x"/>.</returns>
public double Density ( double x )
{
if ( Double . IsPositiveInfinity ( _ invScal e) )
if ( Double . IsPositiveInfinity ( _ rat e) )
{
return x = = _ shape ? Double . PositiveInfinity : 0.0 ;
}
if ( _ shape = = 0.0 & & _ invScal e = = 0.0 )
if ( _ shape = = 0.0 & & _ rat e = = 0.0 )
{
return 0.0 ;
}
if ( _ shape = = 1.0 )
{
return _ invScal e* Math . Exp ( - _ invScal e* x ) ;
return _ rat e* Math . Exp ( - _ rat e* x ) ;
}
return Math . Pow ( _ invScal e, _ shape ) * Math . Pow ( x , _ shape - 1.0 ) * Math . Exp ( - _ invScal e* x ) / SpecialFunctions . Gamma ( _ shape ) ;
return Math . Pow ( _ rat e, _ shape ) * Math . Pow ( x , _ shape - 1.0 ) * Math . Exp ( - _ rat e* x ) / SpecialFunctions . Gamma ( _ shape ) ;
}
/// <summary>
@ -371,22 +367,22 @@ namespace MathNet.Numerics.Distributions
/// <returns>the log density at <paramref name="x"/>.</returns>
public double DensityLn ( double x )
{
if ( Double . IsPositiveInfinity ( _ invScal e) )
if ( Double . IsPositiveInfinity ( _ rat e) )
{
return x = = _ shape ? Double . PositiveInfinity : Double . NegativeInfinity ;
}
if ( _ shape = = 0.0 & & _ invScal e = = 0.0 )
if ( _ shape = = 0.0 & & _ rat e = = 0.0 )
{
return Double . NegativeInfinity ;
}
if ( _ shape = = 1.0 )
{
return Math . Log ( _ invScal e) - ( _ invScal e* x ) ;
return Math . Log ( _ rat e) - ( _ rat e* x ) ;
}
return ( _ shape * Math . Log ( _ invScal e) ) + ( ( _ shape - 1.0 ) * Math . Log ( x ) ) - ( _ invScal e* x ) - SpecialFunctions . GammaLn ( _ shape ) ;
return ( _ shape * Math . Log ( _ rat e) ) + ( ( _ shape - 1.0 ) * Math . Log ( x ) ) - ( _ rat e* x ) - SpecialFunctions . GammaLn ( _ shape ) ;
}
/// <summary>
@ -396,32 +392,32 @@ namespace MathNet.Numerics.Distributions
/// <returns>the cumulative distribution at location <paramref name="x"/>.</returns>
public double CumulativeDistribution ( double x )
{
if ( Double . IsPositiveInfinity ( _ invScal e) )
if ( Double . IsPositiveInfinity ( _ rat e) )
{
return x > = _ shape ? 1.0 : 0.0 ;
}
if ( _ shape = = 0.0 & & _ invScal e = = 0.0 )
if ( _ shape = = 0.0 & & _ rat e = = 0.0 )
{
return 0.0 ;
}
return SpecialFunctions . GammaLowerRegularized ( _ shape , x * _ invScal e) ;
return SpecialFunctions . GammaLowerRegularized ( _ shape , x * _ rat e) ;
}
/// <summary>
/// <para>Sampling implementation based on:
/// "A Simple Method for Generating Gamma Variables" - Marsaglia & Tsang
/// ACM Transactions on Mathematical Software, Vol. 26, No. 3, September 2000, Pages 363–372.</para>
/// ACM Transactions on Mathematical Software, Vol. 26, No. 3, September 2000, Pages 363–372.</para>
/// <para>This method performs no parameter checks.</para>
/// </summary>
/// <param name="rnd">The random number generator to use.</param>
/// <param name="shape">The shape of the Gamma distribution.</param>
/// <param name="invScale">The inverse scale of the Gamma distribution.</param>
/// <param name="shape">The shape (k, α) of the Gamma distribution.</param>
/// <param name="rate">The rate or inverse scale (β) of the Gamma distribution.</param>
/// <returns>A sample from a Gamma distributed random variable.</returns>
internal static double SampleUnchecked ( System . Random rnd , double shape , double invScal e)
internal static double SampleUnchecked ( System . Random rnd , double shape , double rat e)
{
if ( Double . IsPositiveInfinity ( invScal e) )
if ( Double . IsPositiveInfinity ( rat e) )
{
return shape ;
}
@ -453,12 +449,12 @@ namespace MathNet.Numerics.Distributions
x = x * x ;
if ( u < 1.0 - ( 0.0331 * x * x ) )
{
return alphafix * d * v / invScal e;
return alphafix * d * v / rat e;
}
if ( Math . Log ( u ) < ( 0.5 * x ) + ( d * ( 1.0 - v + Math . Log ( v ) ) ) )
{
return alphafix * d * v / invScal e;
return alphafix * d * v / rat e;
}
}
}
@ -469,7 +465,7 @@ namespace MathNet.Numerics.Distributions
/// <returns>a sample from the distribution.</returns>
public double Sample ( )
{
return SampleUnchecked ( RandomSource , _ shape , _ invScal e) ;
return SampleUnchecked ( RandomSource , _ shape , _ rat e) ;
}
/// <summary>
@ -480,7 +476,7 @@ namespace MathNet.Numerics.Distributions
{
while ( true )
{
yield return SampleUnchecked ( RandomSource , _ shape , _ invScal e) ;
yield return SampleUnchecked ( RandomSource , _ shape , _ rat e) ;
}
}
@ -488,36 +484,36 @@ namespace MathNet.Numerics.Distributions
/// Generates a sample from the Gamma distribution.
/// </summary>
/// <param name="rng">The random number generator to use.</param>
/// <param name="shape">The shape of the Gamma distribution from which to generate samples .</param>
/// <param name="invScale">The inverse scale of the Gamma distribution from which to generate samples .</param>
/// <param name="shape">The shape (k, α) of the Gamma distribution.</param>
/// <param name="rate">The rate or inverse scale (β) of the Gamma distribution .</param>
/// <returns>a sample from the distribution.</returns>
public static double Sample ( System . Random rng , double shape , double invScal e)
public static double Sample ( System . Random rng , double shape , double rat e)
{
if ( Control . CheckDistributionParameters & & ! IsValidParameterSet ( shape , invScal e) )
if ( Control . CheckDistributionParameters & & ! IsValidParameterSet ( shape , rat e) )
{
throw new ArgumentOutOfRangeException ( Resources . InvalidDistributionParameters ) ;
}
return SampleUnchecked ( rng , shape , invScal e) ;
return SampleUnchecked ( rng , shape , rat e) ;
}
/// <summary>
/// Generates a sequence of samples from the Gamma distribution.
/// </summary>
/// <param name="rng">The random number generator to use.</param>
/// <param name="shape">The shape of the Gamma distribution from which to generate samples .</param>
/// <param name="invScale">The inverse scale of the Gamma distribution from which to generate samples .</param>
/// <param name="shape">The shape (k, α) of the Gamma distribution.</param>
/// <param name="rate">The rate or inverse scale (β) of the Gamma distribution .</param>
/// <returns>a sequence of samples from the distribution.</returns>
public static IEnumerable < double > Samples ( System . Random rng , double shape , double invScal e)
public static IEnumerable < double > Samples ( System . Random rng , double shape , double rat e)
{
if ( Control . CheckDistributionParameters & & ! IsValidParameterSet ( shape , invScal e) )
if ( Control . CheckDistributionParameters & & ! IsValidParameterSet ( shape , rat e) )
{
throw new ArgumentOutOfRangeException ( Resources . InvalidDistributionParameters ) ;
}
while ( true )
{
yield return SampleUnchecked ( rng , shape , invScal e) ;
yield return SampleUnchecked ( rng , shape , rat e) ;
}
}
}