Пример #1
0
        /// <summary>
        ///   Owen's T function for a restricted range of parameters.
        /// </summary>
        ///
        /// <param name="h">Owen's T function argument H (where 0 &lt;= H).</param>
        /// <param name="a">Owen's T function argument A (where 0 &lt;= A &lt;= 1).</param>
        /// <param name="ah">The value of A*H.</param>
        ///
        /// <returns>The value of Owen's T function.</returns>
        ///
        public static double Function(double h, double a, double ah)
        {
            double ai;
            double aj;
            double AS;
            double dhs;
            double dj;
            double gj;

            double hs;
            int    i;
            int    iaint;
            int    icode;
            int    ihint;
            int    ii;
            int    j;
            int    jj;
            int    m;
            int    maxii;
            double normh;

            double       r;
            const double rrtpi  = 0.39894228040143267794;
            const double rtwopi = 0.15915494309189533577;

            double y;
            double yi;
            double z;
            double zi;

            double value = 0;
            double vi;

            double[] arange =
            {
                0.025, 0.09, 0.15, 0.36, 0.5,
                0.9, 0.99999
            };

            double[] c2 =
            {
                0.99999999999999987510,
                -0.99999999999988796462,         0.99999999998290743652,
                -0.99999999896282500134,         0.99999996660459362918,
                -0.99999933986272476760,         0.99999125611136965852,
                -0.99991777624463387686,         0.99942835555870132569,
                -0.99697311720723000295,         0.98751448037275303682,
                -0.95915857980572882813,         0.89246305511006708555,
                -0.76893425990463999675,         0.58893528468484693250,
                -0.38380345160440256652,         0.20317601701045299653,
                -0.82813631607004984866E-01, 0.24167984735759576523E-01,
                -0.44676566663971825242E-02, 0.39141169402373836468E-03
            };

            double[] hrange =
            {
                0.02, 0.06, 0.09, 0.125, 0.26,
                0.4,   0.6,  1.6,   1.7, 2.33,
                2.4,  3.36,  3.4, 4.8
            };


            int[] meth =
            {
                1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 4, 4, 5, 6
            };

            int[] ord =
            {
                2, 3, 4, 5, 7, 10, 12, 18, 10, 20, 30, 20, 4, 7, 8, 20, 13, 0
            };

            double[] pts =
            {
                0.35082039676451715489E-02,
                0.31279042338030753740E-01, 0.85266826283219451090E-01,
                0.16245071730812277011,         0.25851196049125434828,
                0.36807553840697533536,         0.48501092905604697475,
                0.60277514152618576821,         0.71477884217753226516,
                0.81475510988760098605,         0.89711029755948965867,
                0.95723808085944261843, 0.99178832974629703586
            };

            int[] select =
            {
                1, 1, 2, 13, 13, 13, 13, 13, 13, 13, 13, 16, 16, 16,  9,
                1, 2, 2,  3,  3,  5,  5, 14, 14, 15, 15, 16, 16, 16,  9,
                2, 2, 3,  3,  3,  5,  5, 15, 15, 15, 15, 16, 16, 16, 10,
                2, 2, 3,  5,  5,  5,  5,  7,  7, 16, 16, 16, 16, 16, 10,
                2, 3, 3,  5,  5,  6,  6,  8,  8, 17, 17, 17, 12, 12, 11,
                2, 3, 5,  5,  5,  6,  6,  8,  8, 17, 17, 17, 12, 12, 12,
                2, 3, 4,  4,  6,  6,  8,  8, 17, 17, 17, 17, 17, 12, 12,
                2, 3, 4,  4,  6,  6, 18, 18, 18, 18, 17, 17, 17, 12, 12
            };



            double[] wts =
            {
                0.18831438115323502887E-01,
                0.18567086243977649478E-01, 0.18042093461223385584E-01,
                0.17263829606398753364E-01, 0.16243219975989856730E-01,
                0.14994592034116704829E-01, 0.13535474469662088392E-01,
                0.11886351605820165233E-01, 0.10070377242777431897E-01,
                0.81130545742299586629E-02, 0.60419009528470238773E-02,
                0.38862217010742057883E-02, 0.16793031084546090448E-02
            };



            /*
             * Determine appropriate method from t1...t6
             */
            ihint = 15;

            for (i = 1; i <= 14; i++)
            {
                if (h <= hrange[i - 1])
                {
                    ihint = i;
                    break;
                }
            }

            iaint = 8;

            for (i = 1; i <= 7; i++)
            {
                if (a <= arange[i - 1])
                {
                    iaint = i;
                    break;
                }
            }

            icode = select[ihint - 1 + (iaint - 1) * 15];
            m     = ord[icode - 1];

            /*
             * t1(h, a, m) ; m = 2, 3, 4, 5, 7, 10, 12 or 18
             * jj = 2j - 1 ; gj = exp(-h*h/2) * (-h*h/2)**j / j
             * aj = a**(2j-1) / (2*pi)
             */

            if (meth[icode - 1] == 1)
            {
                hs    = -0.5 * h * h;
                dhs   = Math.Exp(hs);
                AS    = a * a;
                j     = 1;
                jj    = 1;
                aj    = rtwopi * a;
                value = rtwopi * Math.Atan(a);
                dj    = dhs - 1.0;
                gj    = hs * dhs;

                for (; ;)
                {
                    value = value + dj * aj / (double)(jj);

                    if (m <= j)
                    {
                        return(value);
                    }
                    j  = j + 1;
                    jj = jj + 2;
                    aj = aj * AS;
                    dj = gj - dj;
                    gj = gj * hs / (double)(j);
                }
            }

            /*
             * t2(h, a, m) ; m = 10, 20 or 30
             * z = (-1)^(i-1) * zi ; ii = 2i - 1
             * vi = (-1)^(i-1) * a^(2i-1) * exp[-(a*h)^2/2] / sqrt(2*pi)
             */
            else if (meth[icode - 1] == 2)
            {
                maxii = m + m + 1;
                ii    = 1;
                value = 0.0;
                hs    = h * h;
                AS    = -a * a;
                vi    = rrtpi * a * Math.Exp(-0.5 * ah * ah);
                z     = 0.5 * (-0.5 + Normal.Function(ah)) / h;
                y     = 1.0 / hs;

                for (; ;)
                {
                    value = value + z;

                    if (maxii <= ii)
                    {
                        value = value * rrtpi * Math.Exp(-0.5 * hs);
                        return(value);
                    }
                    z  = y * (vi - (double)(ii) * z);
                    vi = AS * vi;
                    ii = ii + 2;
                }
            }

            /*
             * t3(h, a, m) ; m = 20
             * ii = 2i - 1
             * vi = a**(2i-1) * exp[-(a*h)**2/2] / sqrt(2*pi)
             */
            else if (meth[icode - 1] == 3)
            {
                i     = 1;
                ii    = 1;
                value = 0.0;
                hs    = h * h;
                AS    = a * a;
                vi    = rrtpi * a * Math.Exp(-0.5 * ah * ah);
                zi    = 0.5 * (-0.5 + Normal.Function(ah)) / h;
                y     = 1.0 / hs;

                for (; ;)
                {
                    value = value + zi * c2[i - 1];

                    if (m < i)
                    {
                        value = value * rrtpi * Math.Exp(-0.5 * hs);
                        return(value);
                    }
                    zi = y * ((double)(ii) * zi - vi);
                    vi = AS * vi;
                    i  = i + 1;
                    ii = ii + 2;
                }
            }

            /*
             * t4(h, a, m) ; m = 4, 7, 8 or 20;  ii = 2i + 1
             * ai = a * exp[-h*h*(1+a*a)/2] * (-a*a)**i / (2*pi)
             */
            else if (meth[icode - 1] == 4)
            {
                maxii = m + m + 1;
                ii    = 1;
                hs    = h * h;
                AS    = -a * a;
                value = 0.0;
                ai    = rtwopi * a * Math.Exp(-0.5 * hs * (1.0 - AS));
                yi    = 1.0;

                for (; ;)
                {
                    value = value + ai * yi;

                    if (maxii <= ii)
                    {
                        return(value);
                    }
                    ii = ii + 2;
                    yi = (1.0 - hs * yi) / (double)(ii);
                    ai = ai * AS;
                }
            }

            /*
             * t5(h, a, m) ; m = 13
             * 2m - point gaussian quadrature
             */
            else if (meth[icode - 1] == 5)
            {
                value = 0.0;
                AS    = a * a;
                hs    = -0.5 * h * h;
                for (i = 1; i <= m; i++)
                {
                    r     = 1.0 + AS * pts[i - 1];
                    value = value + wts[i - 1] * Math.Exp(hs * r) / r;
                }
                value = a * value;
            }

            /*
             * t6(h, a);  approximation for a near 1, (a<=1)
             */
            else if (meth[icode - 1] == 6)
            {
                normh = Normal.Complemented(h);
                value = 0.5 * normh * (1.0 - normh);
                y     = 1.0 - a;
                r     = Math.Atan(y / (1.0 + a));

                if (r != 0.0)
                {
                    value = value - rtwopi * r * Math.Exp(-0.5 * y * h * h / r);
                }
            }
            return(value);
        }