Skip to content

Commit bcdcb51

Browse files
authored
Merge pull request scipy#21354 from mdhaber/gh20048
2 parents 4d2f88a + 83805fe commit bcdcb51

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

scipy/stats/_distn_infrastructure.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3065,34 +3065,47 @@ def _drv2_ppfsingle(self, q, *args): # Use basic bisection algorithm
30653065
_a, _b = self._get_support(*args)
30663066
b = _b
30673067
a = _a
3068+
3069+
step = 10
30683070
if isinf(b): # Be sure ending point is > q
3069-
b = int(max(100*q, 10))
3071+
b = float(max(100*q, 10))
30703072
while 1:
30713073
if b >= _b:
30723074
qb = 1.0
30733075
break
30743076
qb = self._cdf(b, *args)
30753077
if (qb < q):
3076-
b += 10
3078+
b += step
3079+
step *= 2
30773080
else:
30783081
break
30793082
else:
30803083
qb = 1.0
3084+
3085+
step = 10
30813086
if isinf(a): # be sure starting point < q
3082-
a = int(min(-100*q, -10))
3087+
a = float(min(-100*q, -10))
30833088
while 1:
30843089
if a <= _a:
30853090
qb = 0.0
30863091
break
30873092
qa = self._cdf(a, *args)
30883093
if (qa > q):
3089-
a -= 10
3094+
a -= step
3095+
step *= 2
30903096
else:
30913097
break
30923098
else:
30933099
qa = self._cdf(a, *args)
30943100

3095-
while 1:
3101+
if np.isinf(a) or np.isinf(b):
3102+
message = "Arguments that bracket the requested quantile could not be found."
3103+
raise RuntimeError(message)
3104+
3105+
# maximum number of bisections within the normal float64s
3106+
# maxiter = int(np.log2(finfo.max) - np.log2(finfo.smallest_normal))
3107+
maxiter = 2046
3108+
for i in range(maxiter):
30963109
if (qa == q):
30973110
return a
30983111
if (qb == q):

scipy/stats/tests/test_discrete_distns.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22
import itertools
33

4+
from scipy import stats
45
from scipy.stats import (betabinom, betanbinom, hypergeom, nhypergeom,
56
bernoulli, boltzmann, skellam, zipf, zipfian, binom,
67
nbinom, nchypergeom_fisher, nchypergeom_wallenius,
@@ -648,6 +649,20 @@ def test_gh20692(self):
648649
assert_equal(pmf, pmf_k_int32)
649650

650651

652+
def test_gh20048():
653+
# gh-20048 reported an infinite loop in _drv2_ppfsingle
654+
# check that the one identified is resolved
655+
class test_dist_gen(stats.rv_discrete):
656+
def _cdf(self, k):
657+
return min(k / 100, 0.99)
658+
659+
test_dist = test_dist_gen(b=np.inf)
660+
661+
message = "Arguments that bracket..."
662+
with pytest.raises(RuntimeError, match=message):
663+
test_dist.ppf(0.999)
664+
665+
651666
class TestPoissonBinomial:
652667
def test_pmf(self):
653668
# Test pmf against R `poisbinom` to confirm that this is indeed the Poisson

0 commit comments

Comments
 (0)