/// <summary> /// Jacobi の楕円関数 cn u を求める。 /// </summary> /// <param name="u">引数 u</param> /// <param name="m">率 k の2乗</param> /// <returns>cn(u, k)</returns> public static double Cn(double u, double m) { if (m < 0.0 || m > 1.0) { return(double.NaN); } return(Math.Cos(Elliptic.Phi(u, m))); }
/// <summary> /// Jacobi の楕円関数 dn u を求める。 /// </summary> /// <param name="u">引数 u</param> /// <param name="m">率 k の2乗</param> /// <returns>dn(u, k)</returns> public static double Dn(double u, double m) { if (m < 0.0 || m > 1.0) { return(double.NaN); } double sn = Elliptic.Sn(u, m); return(Math.Sqrt(1 - m * sn * sn)); }
/// <summary> /// Jacobi の楕円関数(引数 u と率 k から振幅φおよび sn, cn, dn)を求める。 /// </summary> /// <param name="u">引数 u</param> /// <param name="m">率 k の2乗</param> /// <param name="phi">振幅φ</param> /// <param name="sn">sn(u, k)</param> /// <param name="cn">cn(u, k)</param> /// <param name="dn">dn(u, k)</param> public static void Jacobi(double u, double m, out double phi, out double sn, out double cn, out double dn) { if (m < 0.0 || m > 1.0) { phi = double.NaN; sn = double.NaN; cn = double.NaN; dn = double.NaN; return; } if (m < EPSILON) { double t = Math.Sin(u); double b = Math.Cos(u); double ai = 0.25 * m * (u - t * b); phi = u - ai; sn = t - ai * b; cn = b + ai * t; dn = 1.0 - 0.5 * m * t * t; return; } if (m >= 1 - EPSILON) { double ai = 0.25 * (1.0 - m); double b = Math.Cosh(u); double t = Math.Tanh(u); double binv = 1.0 / b; double twon = b * Math.Sinh(u); phi = 2.0 * Math.Atan(Math.Exp(u)) - Constant.PI2 + ai * (twon - u) / b; sn = t + ai * (twon - u) / (b * b); ai *= t * phi; cn = binv - ai * (twon - u); dn = binv + ai * (twon + u); return; } phi = Elliptic.Phi(u, m); Elliptic.Jacobi(phi, m, out sn, out cn, out dn); }
/// <summary> /// 第1種不完全楕円積分。 /// </summary> /// <param name="phi">振幅φ</param> /// <param name="m">率 k の2乗</param> /// <returns>積分値</returns> public static double F(double phi, double m) { if (m == 0.0) { return(phi); } if (m == 1.0) { if (Math.Abs(phi) >= Math.PI / 2) { return(double.NaN); } return(Math.Log(Math.Tan((Math.PI / 2 + phi) / 2.0))); } int npio2 = (int)Math.Floor(phi / (Math.PI / 2)); if ((npio2 & 1) != 0) { ++npio2; } double K = npio2 == 0 ? Elliptic.K(1.0 - m) : 0.0; phi -= npio2 * Math.PI / 2; int sign = phi < 0.0 ? -1 : 1; phi = Math.Abs(phi); double t = Math.Tan(phi); if (Math.Abs(t) > 10.0) { /* Transform the amplitude */ double e = 1.0 / (Math.Sqrt(1.0 - m) * t); /* ... but avoid multiple recursions. */ if (Math.Abs(e) < 10.0) { if (npio2 == 0) { K = Elliptic.K(1.0 - m); } double ret = K - Elliptic.F(Math.Atan(e), m); return(sign * ret + npio2 * K); } } double a = 1.0; double b = Math.Sqrt(1.0 - m); double c = Math.Sqrt(m); int d = 1; int mod = 0; while (Math.Abs(c / a) > EPSILON) { double tmp = b / a; phi = phi + (Math.Atan(t * tmp) + mod * Math.PI); mod = (int)((phi + Math.PI / 2) / Math.PI); t = t * (1.0 + tmp) / (1.0 - tmp * t * t); c = (a - b) / 2.0; tmp = Math.Sqrt(a * b); a = (a + b) / 2.0; b = tmp; d += d; } return(sign * (Math.Atan(t) + mod * Math.PI) / (d * a) + npio2 * K); }