/// <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); } }
/// <summary> /// Computes the complex digamma (ψ) function. /// </summary> /// <param name="z">The complex argument.</param> /// <returns>The value of ψ(z).</returns> /// <remarks> /// <para>The image below shows the complex ψ function near the origin using domain coloring.</para> /// <img src="../images/ComplexPsiPlot.png" /> /// </remarks> /// <seealso cref="AdvancedMath.Psi(double)" /> public static Complex Psi(Complex z) { if (z.Re < 0.5) { // reduce z.Re in order to handle large real values! return(Psi(1.0 - z) - Math.PI / ComplexMath.Tan(Math.PI * z)); } else { // add Stirling for large z return(Lanczos.Psi(z)); } }