/// <summary> /// Returns the value of the Airy Ai function at <paramref name="x"/> /// </summary> /// <param name="x">The function argument</param> /// <returns></returns> public static double AiryAi(double x) { if (double.IsNaN(x)) { Policies.ReportDomainError("AiryAi(x: {0}): NaN not allowed", x); return(double.NaN); } if (double.IsInfinity(x)) { return(0); } double absX = Math.Abs(x); if (x >= -3 && x <= 2) { // Use small series. See: // http://functions.wolfram.com/Bessel-TypeFunctions/AiryAi/06/01/02/01/0004/ // http://dlmf.nist.gov/9.4 double z = x * x * x / 9; double s1 = Constants.AiryAi0 * HypergeometricSeries.Sum0F1(2 / 3.0, z); double s2 = x * Constants.AiryAiPrime0 * HypergeometricSeries.Sum0F1(4 / 3.0, z); return(s1 + s2); } const double v = 1.0 / 3; double zeta = 2 * absX * Math.Sqrt(absX) / 3; if (x < 0) { if (x < -32) { return(AiryAsym.AiBiNeg(x).Ai); } // The following is //double j1 = Math2.BesselJ(v, zeta); //double j2 = Math2.BesselJ(-v, zeta); //double ai = Math.Sqrt(-x) * (j1 + j2) / 3; var(J, Y) = _Bessel.JY(v, zeta, true, true); double s = 0.5 * (J - ((double)Y) / Constants.Sqrt3); double ai = Math.Sqrt(-x) * s; return(ai); } else { // Use the K relationship: http://dlmf.nist.gov/9.6 if (x >= 16) { return(AiryAsym.Ai(x)); } double ai = Math2.BesselK(v, zeta) * Math.Sqrt(x / 3) / Math.PI; return(ai); } }
/// <summary> /// Returns the value of the Airy Bi function at <paramref name="x"/> /// </summary> /// <param name="x">The function argument</param> /// <returns></returns> public static double AiryBi(double x) { if (double.IsNaN(x)) { Policies.ReportDomainError("AiryBi(x: {0}): NaN not allowed", x); return(double.NaN); } if (double.IsInfinity(x)) { if (x < 0) { return(0); } return(double.PositiveInfinity); } double absX = Math.Abs(x); if (x >= -3 && x <= 3) { // Use small series. See: // http://functions.wolfram.com/Bessel-TypeFunctions/AiryBi/26/01/01/ // http://dlmf.nist.gov/9.4 double z = x * x * x / 9; double s1 = Constants.AiryBi0 * HypergeometricSeries.Sum0F1(2 / 3.0, z); double s2 = x * Constants.AiryBiPrime0 * HypergeometricSeries.Sum0F1(4 / 3.0, z); return(s1 + s2); } const double v = 1.0 / 3; double zeta = (absX * Math.Sqrt(absX) * 2) / 3; if (x < 0) { if (x < -32) { return(AiryAsym.AiBiNeg(x).Bi); } // The following is //double j1 = Math2.BesselJ(v, zeta); //double j2 = Math2.BesselJ(-v, zeta); //double bi = Math.Sqrt(-x / 3) * (j2 - j1); var(J, Y) = _Bessel.JY(v, zeta, true, true); double s = -0.5 * (J / Constants.Sqrt3 + ((double)Y)); double bi = Math.Sqrt(-x) * s; return(bi); } else { if (x >= 16) { return(AiryAsym.Bi(x)); } // The following is //double j1 = Math2.BesselI(v, zeta); //double j2 = Math2.BesselI(-v, zeta); //double bi = Math.Sqrt(x / 3) * (j1 + j2); var(I, K) = _Bessel.IK(v, zeta, true, true); double s = (2 / Constants.Sqrt3 * I + K / Math.PI); var bi = Math.Sqrt(x) * s; return(bi); } }