楕円積分/楕円関数関連の static メソッド群を定義。
u = ∫ dφ/Δ(φ) Δ(φ) = √(1 - k^2 sin^2 φ) z = sn u = sin φ cn u = cos φ dn = √(1 - k^2 sn^2)
Beispiel #1
0
        /// <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)));
        }
Beispiel #2
0
        /// <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));
        }
Beispiel #3
0
        /// <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);
        }
Beispiel #4
0
        /// <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);
        }