diff --git a/scipy/stats/_continuous_distns.py b/scipy/stats/_continuous_distns.py index a9f679b9be50..390d97db3d03 100644 --- a/scipy/stats/_continuous_distns.py +++ b/scipy/stats/_continuous_distns.py @@ -4214,7 +4214,7 @@ class halflogistic_gen(rv_continuous): References ---------- .. [1] Asgharzadeh et al (2011). "Comparisons of Methods of Estimation for the - Half-Logistic Distribution". Selcuk J. Appl. Math. 93-108. + Half-Logistic Distribution". Selcuk J. Appl. Math. 93-108. %(example)s @@ -4439,6 +4439,12 @@ def _cdf(self, x): def _ppf(self, q): return np.log(np.tan(np.pi*q/2.0)) + def _sf(self, x): + return 2.0/np.pi*np.arctan(np.exp(-x)) + + def _isf(self, q): + return -np.log(np.tan(np.pi*q/2.0)) + def _stats(self): return 0, np.pi*np.pi/4, 0, 2 diff --git a/scipy/stats/tests/test_distributions.py b/scipy/stats/tests/test_distributions.py index 26ee1655667d..0a75b976a76d 100644 --- a/scipy/stats/tests/test_distributions.py +++ b/scipy/stats/tests/test_distributions.py @@ -841,6 +841,29 @@ def test_pdf_norminvgauss(self): ) +class TestHypSecant: + + # Reference values were computed with the mpmath expression + # float((2/mp.pi)*mp.atan(mp.exp(-x))) + # and mp.dps = 50. + @pytest.mark.parametrize('x, reference', + [(30, 5.957247804324683e-14), + (50, 1.2278802891647964e-22)]) + def test_sf(self, x, reference): + sf = stats.hypsecant.sf(x) + assert_allclose(sf, reference, rtol=5e-15) + + # Reference values were computed with the mpmath expression + # float(-mp.log(mp.tan((mp.pi/2)*p))) + # and mp.dps = 50. + @pytest.mark.parametrize('p, reference', + [(1e-6, 13.363927852673998), + (1e-12, 27.179438410639094)]) + def test_isf(self, p, reference): + x = stats.hypsecant.isf(p) + assert_allclose(x, reference, rtol=5e-15) + + class TestNormInvGauss: def setup_method(self): np.random.seed(1234) @@ -1873,14 +1896,14 @@ def test_rvs(self, c): (1e10, -10.093986931748889), (1e100, -113.71031611649761)]) def test_entropy(self, c, ref): - + # Reference values were calculated with mpmath # from mpmath import mp # mp.dps = 500 # def loggamma_entropy_mpmath(c): # c = mp.mpf(c) # return float(mp.log(mp.gamma(c)) + c * (mp.one - mp.digamma(c))) - + assert_allclose(stats.loggamma.entropy(c), ref, rtol=1e-14) @@ -3415,7 +3438,6 @@ def test_t_inf_df_stats_entropy(self, df_infmask): assert_equal(res[df_infmask], res_ex_inf) assert_equal(res[~df_infmask], res_ex_noinf) - def test_logpdf_pdf(self): # reference values were computed via the reference distribution, e.g. # mp.dps = 500; StudentT(df=df).logpdf(x), StudentT(df=df).pdf(x) @@ -4020,6 +4042,7 @@ def test_cdf_ppf(self, x, p, a, b, c): ppf = stats.genexpon.ppf(p, a, b, c) assert_allclose(ppf, x, rtol=1e-14) + class TestTruncexpon: def test_sf_isf(self): @@ -5517,6 +5540,7 @@ def test_x_near_zeta( expected, ) + class TestArrayArgument: # test for ticket:992 def setup_method(self): np.random.seed(1234)