Accord.Math.Normal.BVND C# (CSharp) Метод

BVND() приватный статический Метод

A function for computing bivariate normal probabilities. BVND calculates the probability that X > DH and Y > DK.

This method is based on the work done by Alan Genz, Department of Mathematics, Washington State University. Pullman, WA 99164-3113 Email: [email protected]. This work was shared under a 3-clause BSD license. Please see source file for more details and the actual license text.

This function is based on the method described by Drezner, Z and G.O. Wesolowsky, (1989), On the computation of the bivariate normal integral, Journal of Statist. Comput. Simul. 35, pp. 101-107, with major modifications for double precision, and for |R| close to 1.

private static BVND ( double dh, double dk, double r ) : double
dh double
dk double
r double
Результат double
        private static double BVND(double dh, double dk, double r)
        {
            // Copyright (C) 2013, Alan Genz,  All rights reserved.               
            // 
            //  Redistribution and use in source and binary forms, with or without
            //  modification, are permitted provided the following conditions are met:
            //    1. Redistributions of source code must retain the above copyright
            //       notice, this list of conditions and the following disclaimer.
            //    2. Redistributions in binary form must reproduce the above copyright
            //       notice, this list of conditions and the following disclaimer in 
            //       the documentation and/or other materials provided with the 
            //       distribution.
            //    3. The contributor name(s) may not be used to endorse or promote 
            //       products derived from this software without specific prior 
            //       written permission.
            //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
            //  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
            //  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
            //  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
            //  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
            //  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
            //  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
            //  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
            //  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
            //  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF USE
            //  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

            const double TWOPI = 2.0 * Math.PI;

            double[] x;
            double[] w;

            if (Math.Abs(r) < 0.3)
            {
                // Gauss Legendre Points and Weights N =  6
                x = BVND_XN6;
                w = BVND_WN6;
            }
            else if (Math.Abs(r) < 0.75)
            {
                // Gauss Legendre Points and Weights N =  12
                x = BVND_XN12;
                w = BVND_WN12;
            }
            else
            {
                // Gauss Legendre Points and Weights N =  20
                x = BVND_XN20;
                w = BVND_WN20;
            }

            double h = dh;
            double k = dk;
            double hk = h * k;
            double bvn = 0;

            if (Math.Abs(r) < 0.925)
            {
                if (Math.Abs(r) > 0)
                {
                    double sh = (h * h + k * k) / 2;
                    double asr = Math.Asin(r);

                    for (int i = 0; i < x.Length; i++)
                    {
                        for (int j = -1; j <= 1; j += 2)
                        {
                            double sn = Math.Sin(asr * (j * x[i] + 1) / 2);
                            bvn = bvn + w[i] * Math.Exp((sn * hk - sh) / (1 - sn * sn));
                        }
                    }
                    bvn = bvn * asr / (2 * TWOPI);
                }

                return bvn + Normal.Function(-h) * Normal.Function(-k);
            }


            if (r < 0)
            {
                k = -k;
                hk = -hk;
            }

            if (Math.Abs(r) < 1)
            {
                double sa = (1 - r) * (1 + r);
                double A = Math.Sqrt(sa);
                double sb = (h - k);
                sb = sb * sb;
                double c = (4 - hk) / 8;
                double d = (12 - hk) / 16;
                double asr = -(sb / sa + hk) / 2;

                if (asr > -100)
                    bvn = A * Math.Exp(asr) * (1 - c * (sb - sa) * (1 - d * sb / 5) / 3 + c * d * sa * sa / 5);

                if (-hk < 100)
                {
                    double B = Math.Sqrt(sb);
                    bvn = bvn - Math.Exp(-hk / 2) * Math.Sqrt(TWOPI) * Normal.Function(-B / A) * B
                              * (1 - c * sb * (1 - d * sb / 5) / 3);
                }

                A = A / 2;

                for (int i = 0; i < x.Length; i++)
                {
                    for (int j = -1; j <= 1; j += 2)
                    {
                        double xs = (A * (j * x[i] + 1));
                        xs = xs * xs;
                        double rs = Math.Sqrt(1 - xs);
                        asr = -(sb / xs + hk) / 2;

                        if (asr > -100)
                        {
                            bvn = bvn + A * w[i] * Math.Exp(asr)
                                * (Math.Exp(-hk * xs / (2 * (1 + rs) * (1 + rs))) / rs
                                - (1 + c * xs * (1 + d * xs)));
                        }
                    }
                }

                bvn = -bvn / TWOPI;
            }

            if (r > 0)
                return bvn + Normal.Function(-Math.Max(h, k));

            bvn = -bvn;

            if (k <= h)
                return bvn;

            if (h < 0)
                return bvn + Normal.Function(k) - Normal.Function(h);

            return bvn + Normal.Function(-h) - Normal.Function(-k);
        }