Пример #1
0
        private long SampleUsingInversion()
        {
            var px = qn;
            var U  = RandomState.NextDouble();
            var X  = 0L;

            while (U > px)
            {
                X++;
                if (X > bound)
                {
                    X  = 0;
                    px = qn;
                    U  = RandomState.NextDouble();
                }
                else
                {
                    U -= px;
                    px = ((NSamples - X + 1) * SuccessProbability * px) / (X * FailureProbability);
                }
            }
            return(X);
        }
Пример #2
0
        private long SampleUsingBTPE()
        {
            // The following code is ported from NumPy's binomial
            // sampling implementation.
            double r, q, fm, p1, xm, xl, xr, c, laml, lamr, p2, p3, p4;
            double a, u, v, s, F, rho, t, A, nrq, x1, x2, f1, f2, z, z2, w, w2, x;
            long   m, y, k, i;

            /* initialize */
            r    = Min(SuccessProbability, FailureProbability);
            q    = 1.0 - r;
            fm   = NSamples * r + r;
            m    = (long)Floor(fm);
            p1   = Floor(2.195 * Sqrt(NSamples * r * q) - 4.6 * q) + 0.5;
            xm   = m + 0.5;
            xl   = xm - p1;
            xr   = xm + p1;
            c    = 0.134 + 20.5 / (15.3 + m);
            a    = (fm - xl) / (fm - xl * r);
            laml = a * (1.0 + a / 2.0);
            a    = (xr - fm) / (xr * q);
            lamr = a * (1.0 + a / 2.0);
            p2   = p1 * (1.0 + 2.0 * c);
            p3   = p2 + c / laml;
            p4   = p3 + c / lamr;


            /* sigh ... */
Step10:
            nrq = NSamples * r * q;
            u   = RandomState.NextDouble() * p4;
            v   = RandomState.NextDouble();
            if (u > p1)
            {
                goto Step20;
            }
            y = (long)Floor(xm - p1 * v + u);
            goto Step60;

Step20:
            if (u > p2)
            {
                goto Step30;
            }
            x = xl + (u - p1) / c;
            v = v * c + 1.0 - Abs(m - x + 0.5) / p1;
            if (v > 1.0)
            {
                goto Step10;
            }
            y = (long)Floor(x);
            goto Step50;

Step30:
            if (u > p3)
            {
                goto Step40;
            }
            y = (long)Floor(xl + Log(v) / laml);
            /* Reject if v == 0.0 since cast of inf not well defined */
            if ((y < 0) || (v == 0.0))
            {
                goto Step10;
            }
            v = v * (u - p2) * laml;
            goto Step50;

Step40:
            y = (long)Floor(xr - Log(v) / lamr);
            /* Reject if v == 0.0 since cast of inf not well defined */
            if ((y > NSamples) || (v == 0.0))
            {
                goto Step10;
            }
            v = v * (u - p3) * lamr;

Step50:
            k = Abs(y - m);
            if ((k > 20) && (k < ((nrq) / 2.0 - 1)))
            {
                goto Step52;
            }

            s = r / q;
            a = s * (NSamples + 1);
            F = 1.0;
            if (m < y)
            {
                for (i = m + 1; i <= y; i++)
                {
                    F *= (a / i - s);
                }
            }
            else if (m > y)
            {
                for (i = y + 1; i <= m; i++)
                {
                    F /= (a / i - s);
                }
            }
            if (v > F)
            {
                goto Step10;
            }
            goto Step60;

Step52:
            rho = (k / (nrq)) * ((k * (k / 3.0 + 0.625) + 0.16666666666666666) / nrq + 0.5);
            t   = -k * k / (2 * nrq); // lgtm [cs/loss-of-precision]
            A   = Log(v);
            if (A < (t - rho))
            {
                goto Step60;
            }
            if (A > (t + rho))
            {
                goto Step10;
            }

            x1 = y + 1;
            f1 = m + 1;
            z  = NSamples + 1 - m;
            w  = NSamples - y + 1;
            x2 = x1 * x1;
            f2 = f1 * f1;
            z2 = z * z;
            w2 = w * w;
            if (A > (xm * Log(f1 / x1)
                     + (NSamples - m + 0.5) * Log(z / w)
                     + (y - m) * Log(w * r / (x1 * q))
                     + (13680.0 - (462.0 - (132.0 - (99.0 - 140.0 / f2) / f2) / f2) / f2) / f1 / 166320.0
                     + (13680.0 - (462.0 - (132.0 - (99.0 - 140.0 / z2) / z2) / z2) / z2) / z / 166320.0
                     + (13680.0 - (462.0 - (132.0 - (99.0 - 140.0 / x2) / x2) / x2) / x2) / x1 / 166320.0
                     + (13680.0 - (462.0 - (132.0 - (99.0 - 140.0 / w2) / w2) / w2) / w2) / w / 166320.0))
            {
                goto Step10;
            }

Step60:
            if (SuccessProbability > 0.5)
            {
                y = NSamples - y;
            }

            return(y);
        }