@Override
    public double rand() {
        // faster calculation by inversion
        boolean inv = p > 0.5;
        double np = n * Math.min(p, 1.0 - p);

        // Poisson's approximation for extremely low np
        int x;
        if (np < 1E-6) {
            x = PoissonDistribution.tinyLambdaRand(np);
        } else {
            RandomNumberGenerator rng;
            if (np < 55) {
                // inversion method, using chop-down search from 0
                if (p <= 0.5) {
                    rng = new ModeSearch(p);
                } else {
                    rng = new ModeSearch(1.0 - p); // faster calculation by inversion
                }
            } else {
                // ratio of uniforms method
                if (p <= 0.5) {
                    rng = new Patchwork(p);
                } else {
                    rng = new Patchwork(1.0 - p); // faster calculation by inversion
                }
            }

            x = rng.rand();
        }

        // undo inversion
        return inv ? n - x : x;
    }
@Test
    public void testRandOverflow() {
        System.out.println("rand overflow");
        MathEx.setSeed(19650218);
        BinomialDistribution instance = new BinomialDistribution(1000, 0.999000999000999);
        assertEquals(999, instance.rand(), 1E-7);
    }