/// <summary> /// Computes the digamma function. /// </summary> /// <param name="x">The argument.</param> /// <returns>The value of ψ(x).</returns> /// <remarks> /// <para>The psi function, also called the digamma function, is the logrithmic derivative of the Γ function.</para> /// <img src="../images/DiGamma.png" /> /// <para>To evaluate the Psi function for complex arguments, use <see cref="AdvancedComplexMath.Psi" />.</para> /// </remarks> /// <seealso cref="Gamma(double)"/> /// <seealso cref="AdvancedComplexMath.Psi"/> /// <seealso href="http://en.wikipedia.org/wiki/Digamma_function" /> /// <seealso href="http://mathworld.wolfram.com/DigammaFunction.html" /> public static double Psi(double x) { if (x <= 0.0) { if (x == Math.Ceiling(x)) { // there are poles at zero and negative integers return(Double.NaN); } else { // use the reflection formula to change to a positive x return(Psi(1.0 - x) - Math.PI / Math.Tan(Math.PI * x)); } } else if (x < 16.0) { return(Lanczos.Psi(x)); } else { // for large arguments, the Stirling asymptotic expansion is faster than the Lanzcos approximation return(Stirling.Psi(x)); //return (Psi_Stirling(x)); } }
/// <summary> /// Computes the digamma function. /// </summary> /// <param name="x">The argument.</param> /// <returns>The value of ψ(x).</returns> /// <remarks> /// <para>The psi function, also called the digamma function, is the logrithmic derivative of the Γ function.</para> /// <img src="../images/DiGamma.png" /> /// <para>Because it is defined as a <i>logarithmic</i> derivative, the digamma function does not overflow <see cref="System.Double"/> /// even for arguments for which <see cref="Gamma(double)"/> does.</para> /// <para>To evaluate the psi function for complex arguments, use <see cref="AdvancedComplexMath.Psi" />.</para> /// </remarks> /// <seealso cref="Gamma(double)"/> /// <seealso cref="AdvancedComplexMath.Psi"/> /// <seealso href="http://en.wikipedia.org/wiki/Digamma_function" /> /// <seealso href="http://mathworld.wolfram.com/DigammaFunction.html" /> public static double Psi(double x) { if (x < 0.5) { return(Psi(1.0 - x) - Math.PI / MoreMath.TanPi(x)); } else if (x < 1.5) { return(GammaSeries.PsiOnePlus(x - 1.0)); } else if (x < 2.5) { return(GammaSeries.PsiTwoPlus(x - 2.0)); } else if (x < 16.0) { return(Lanczos.Psi(x)); } else if (x <= Double.PositiveInfinity) { // For large arguments, the Stirling asymptotic expansion is faster than the Lanzcos approximation return(Stirling.Psi(x)); } else { return(Double.NaN); } }